Chromium Chronicle מס' 13: ניפוי באגים בנסיעות בזמן עם RR

פרק 13: מאת כריסטיאן ביסנגר במדיסון, ויסקונסין (מרץ 2020)
פרקים קודמים

האם אתם מריצים את אותה בדיקה שוב ושוב בכלי לניפוי באגים, כשאתם מנסים להבין איך הקוד לא היה תקין? יש לנו כלי בשבילכם! אפשר להתקין ולהגדיר בקלות את מעקב הביצוע, והוא מעניק ל-gdb כוחות קסומים. חזרה אחורה והרצה אחורה, כדי לראות איפה הערך של המשתנים השתנה, או מתי הפונקציה הופעלה לאחרונה באובייקט (באמצעות נקודות עצירה מותנות).

ב-Linux אפשר להשתמש ב-rr. מתקינים אותו דרך sudo apt-get install rr או דרך הכתובת https://rr-project.org/.

אפשרות זו לא נתמכת באופן רשמי, אבל היא מועילה מאוד. ב-rr אפשר להקליט תחילה מעקב, ולאחר מכן להפעיל אותו מחדש.

rr record .../content_shell --no-sandbox  --disable-hang-monitor --single-process
# record the trace. --single-process is optional, see below. The other flags are required.
rr replay # This will replay the last trace
(gdb)       # rr uses GDB to let you replay traces

באופן נוח, התזמון וכתובות הסמן נשארים ללא שינוי בכל פעם שאתם מפעילים מחדש אותו מעקב. אפשר לנייד את המעקבים באמצעות rr pack, כך שתוכלו להעתיק אותם למחשב אחר ולהפעיל אותם מחדש או להפעיל אותם מחדש גם אחרי הקומפילציה מחדש. מפעילים את התוכנית באמצעות continue. תוכלו להשתמש בכל פקודות GDB הרגילות -b, next, watch וכו'. עם זאת, אפשר גם להשתמש בפקודות reverse-next (rn), reverse-cont (rc), reverse-step (rs), reverse-fin.

הן עדיין מכבדות את נקודות העצירה שהגדרת. לדוגמה:

(gdb) c  # Execute to the end
(gdb) break blink::LayoutFlexibleBox::UpdateLayout
(gdb) rc # Run back to the last layout call
Thread 5 hit Breakpoint 1, blink::LayoutBlock::UpdateLayout (
    this=0x121672224010)
(gdb) # Inspect anything you want here. To find the previous Layout call on this object:
(gdb) cond 1 this == 0x121672224010
(gdb) rc
Thread 5 hit Breakpoint 1, blink::LayoutBlock::UpdateLayout (
    this=0x121672224010)
(gdb) watch -l style_.ptr_ # Or find the last time the style_ was changed
(gdb) rc
Thread 5 hit Hardware watchpoint 2: -location style_.ptr_

Old value = (const blink::ComputedStyle *) 0x1631ad3dbb0
New value = (const blink::ComputedStyle *) 0x0
0x00007f68cabcf78e in std::__Cr::swap<blink::ComputedStyle const*> (

בדוגמה הזו השתמשנו ב---single-process כדי לפשט את העניינים, אבל זה לא הכרחי. RR יכול לעקוב אחר מספר תהליכים. אחרי ההקלטה אפשר לראות רשימה באמצעות rr ps ולבחור תהליך להפעלה מחדש באמצעות rr replay -f PID.

יש הרבה דרכים להפיק תועלת מ-RR. יש פקודות אחרות שאפשר להשתמש בהן, כמו בדיקה מתי לגלות באיזה מספר אירוע אתם נמצאים או rr replay -M כדי להוסיף הערות ל-stdout באמצעות מזהה תהליך ומספר אירוע בכל שורה. פרטים נוספים זמינים באתר של RR ובמסמכים בנושא.