การมีส่วนร่วมกับเคอร์เนลครั้งแรกของผมถูกขโมยไป
(ariel-miculas.github.io)- Ariel Miculas ติดตามปัญหาที่ทำให้ การดีบักแบบมัลติเธรดของ gdbserver บน PowerPC32 ใช้งานไม่ได้ และพบ bug หน่วยความจำเสียหายใน Linux kernel แต่การแก้ไขสุดท้ายถูกรวมเข้าไปเป็นแพตช์แยกของ maintainer ทำให้ได้รับเครดิตเพียง
Reported-by - เบาะแสคือเธรดอีเมลเก่าที่พูดถึงอาการเดียวกัน และคอมมิตที่ เปลี่ยนตำแหน่งของ
thread_struct threadภายในtask_structซึ่งนำไปสู่อาการที่บางเธรดค้างอยู่ในสถานะโปรเซสที่ผิดพลาด และทำให้ gdbserver สูญเสียการควบคุม - การวิเคราะห์สาเหตุใช้
pahole, ftrace และ hardware breakpoint ที่อิง DABR ของ PowerPC และยืนยันได้ว่า buffer overflow ในptrace_put_fprเขียนทับฟิลด์อย่างtask_struct.__state - overflow เกิดจากการนำดัชนีสำหรับ element ขนาด 32 บิตไปใช้กับอาร์เรย์ 64 บิต ทำให้ gdbserver ฝั่งผู้ใช้สามารถเขียนเลยอาร์เรย์
fp_state.fprที่มีเพียง 32 รายการออกไปได้สูงสุดถึง 256 ไบต์ - Michael Ellerman maintainer ของ PowerPC นำแนวทางแก้ไขของตัวเองไปใช้ และในอีเมลตอบกลับภายหลังมี คำขอโทษ ว่าเครดิตเพียง
Reported-byไม่ได้สะท้อนการมีส่วนร่วมอย่างเหมาะสม และควรได้พัฒนาแพตช์ร่วมกัน
การดีบัก gdbserver ที่เสียบน PowerPC32
- ประมาณหนึ่งปีครึ่งก่อน Ariel Miculas ขอเวลาในบริษัทเดิมเพื่อสืบสวนปัญหาที่ขัดขวางความสามารถด้านการดีบักของโปรเจกต์
- ปัญหาคือ gdbserver ไม่สามารถดีบักแอปพลิเคชันแบบมัลติเธรดได้อย่างถูกต้องบนสถาปัตยกรรม PowerPC32
- การเชื่อมต่อ gdbserver หลุด และไม่สามารถควบคุมเซสชันดีบักต่อได้
- ยังไม่แน่ชัดว่าสาเหตุอยู่ที่ toolchain, gdbserver, Linux kernel หรือแพตช์เคอร์เนลแบบ custom
- หลังจากตรวจสอบและค้นหาข้อมูลเดิม พบ เธรดอีเมล ที่พูดถึงอาการเดียวกัน
- เธรดนี้ยังชี้ไปยัง คอมมิต ที่ทำให้เกิดปัญหา
- แพตช์ดังกล่าวเป็นการย้าย definition ของ
thread_struct threadที่เคยอยู่กลางtask_structไปไว้ท้ายสุด
เบาะแสที่ narrowed down จากสถานะเธรดไปสู่หน่วยความจำเสียหาย
- ตามการวิเคราะห์เดิมของ Holger Brunck gdbserver จะส่ง
SIGSTOPไปยังเคอร์เนลสำหรับแต่ละเธรดและรอการตอบกลับ แต่ในสถานการณ์ที่เกิดข้อผิดพลาด เคอร์เนลตอบกลับเพียงบาง signal เท่านั้น - ในระดับล่าง หลังจากโต้ตอบกับ gdbserver แล้ว บางเธรดถูกวางไว้ใน สถานะโปรเซส ที่ผิดพลาด และ gdbserver ก็สูญเสียการควบคุมหลังจากนั้น
- Ariel ใช้เวลา 3–4 วันอ่านคำอธิบายคอมมิตที่เกี่ยวกับ PowerPC และการเปลี่ยนแปลงรอบ ๆ
task_structพร้อมตรวจสอบว่าปัญหาถูกแก้ใน kernel รุ่นถัด ๆ ไปหรือไม่ แต่ไม่พบวิธีแก้ - เขาลองเปลี่ยนตำแหน่งของ
thread_struct threadเพื่อยืนยันเงื่อนไขการ reproduce และใช้ pahole ตรวจดู layout ของtask_struct - ใช้ ftrace ติดตามว่าเธรดของโปรเซสที่ถูกดีบักถูก schedule เมื่อใด
- เธรดที่หยุดค้างถูก schedule เพียงครั้งเดียว ต่างจากเธรดอื่น ๆ
- ข้อสังเกตนี้ทำให้กลับมาพิจารณาความเป็นไปได้เรื่อง หน่วยความจำเสียหาย อีกครั้ง
สาเหตุจริงที่พบด้วย hardware breakpoint
- เขายืนยันได้ว่า PowerPC ก็มีความสามารถคล้ายกับ debug registers ของ x86 โดยใช้ DABR register
- หลังจากศึกษาวิธีใช้ hardware breakpoint บน Linux แล้ว เขาสร้าง kernel module โดยอิงจาก คำตอบใน Stack Overflow
- ใช้โมดูลนี้ตั้ง hardware breakpoint บนฟิลด์
task_struct.__stateเพื่อติดตามว่าใครเขียนค่าเข้าไป - kernel module แบบ custom แสดง stack trace ของตำแหน่งที่เขียนลง
task_struct.__stateและหนึ่งในเส้นทางที่ผิดปกตินำไปสู่ buffer overflow ในptrace_put_fpr ptrace_put_fprถูกใช้ใน POKEUSER API และ overflow นี้เขียนทับฟิลด์สำคัญในtask_structเช่น__state__stateใช้เก็บสถานะของโปรเซส- เคอร์เนลใช้ฟิลด์นี้ด้วยเมื่อติดตามโปรเซสที่ถูก debugger หยุดไว้
การเขียนอาร์เรย์ที่สามารถล้ำออกไปได้ถึง 256 ไบต์
- สาเหตุของ overflow อยู่ที่การนำดัชนีที่ออกแบบมาสำหรับอาร์เรย์ element ขนาด 32 บิตไปใช้กับ อาร์เรย์ element ขนาด 64 บิต
- ดัชนีที่ชี้ไปยัง FPR มี 64 ค่า และช่วงการเข้าถึงเมื่อคิดตาม element 64 บิตคือ
64 * 8 = 512ไบต์ - แต่ในความเป็นจริง อาร์เรย์
fp_state.fprมีเพียง 32 entries และหน่วยความจำที่ใช้ได้คือ32 * 8 = 256ไบต์ - ผลคือผู้ใช้ หรือก็คือ gdbserver สามารถเขียนเลยท้ายอาร์เรย์ออกไปได้สูงสุดถึง 256 ไบต์
การส่ง upstream และข้อขัดแย้งเรื่องเครดิต
- Ariel เห็นว่าปัญหาหน่วยความจำเสียหายที่สามารถเขียนทับหน่วยความจำสถานะโปรเซสได้อาจมีผลกระทบด้านความปลอดภัย จึงส่งแพตช์ไปที่
security@kernel.org- mailing list นี้เป็นแบบไม่สาธารณะ จึงไม่สามารถลิงก์แพตช์ที่ส่งครั้งแรกได้
- Michael Ellerman maintainer ของ PowerPC ติดต่อกลับเป็นการส่วนตัวและบอกว่าจะจัดการปัญหานี้
- Ariel ส่งแพตช์แก้ไข 2 แบบ
- แพตช์เดิมที่ส่งไปยัง mailing list ด้านความปลอดภัย
- แพตช์อีกเวอร์ชันหนึ่ง ที่สะท้อนข้อเสนอแนะต่อ submission เดิม
- แพตช์ที่สองอิงจากโค้ดเคอร์เนลเดิมที่จำลองพฤติกรรม PowerPC32 บน PowerPC64 และโค้ดนั้นจัดการการ indexing ของ FPR ได้อย่างถูกต้อง
- Michael Ellerman ไม่รับแพตช์ทั้งสอง แต่ implement แนวทางแก้ไขของตัวเอง
- Ariel อยากให้แพตช์ของตนเองถูกยอมรับ เพื่อให้ได้รับเครดิตในฐานะผู้แก้ปัญหานี้และในฐานะผู้มีส่วนร่วมกับเคอร์เนลครั้งแรก และเขาก็พร้อมส่งเวอร์ชันถัดไปหลังปรับตาม feedback
- เครดิตที่ได้รับจริงมีเพียงแท็ก
Reported-byและ Ariel รู้สึกว่าไม่ยุติธรรมเมื่อเทียบกับความพยายามที่ลงไปในการวิเคราะห์สาเหตุ แก้ไข ทดสอบ ตรวจสอบ รับ feedback ภายในบริษัท และปรับใช้กับเคอร์เนลล่าสุด- ตามเอกสารของ Linux
Reported-byเป็นแท็กที่ให้เครดิตแก่ผู้พบและรายงาน bug - ปัญหานี้เคยถูกรายงานมาแล้วเมื่อ 6 ปีก่อน
- ตามเอกสารของ Linux
อัปเดตและอีเมลขอโทษตอบกลับ
- ผู้ใช้ Hacker News ชี้ให้เห็น อีเมล ที่ Michael Ellerman เขียนว่า “ขอบคุณสำหรับแพตช์ แต่ผมอยากแก้ด้วยวิธีที่ต่างออกไป คุณช่วยลองทดสอบแพตช์ด้านล่างเพื่อยืนยันว่า bug ถูกแก้แล้วได้ไหม”
- อีเมลนี้แสดงให้เห็นว่า Michael Ellerman เลือก implement เองแทนที่จะ review แพตช์ของ Ariel และขอให้ Ariel ทดสอบแพตช์นั้น
- Ariel หาแพตช์เดิมที่เคยส่งไปยัง mailing list ด้านความปลอดภัย แล้ว forward เธรดอีเมล ไปยัง linuxppc-dev
- ในอัปเดตภายหลังมีอีเมลตอบกลับที่ขอโทษเรื่องวิธีจัดการแพตช์
- มีข้อความว่า “ผมน่าจะใช้เวลากับการพัฒนาแพตช์ของคุณร่วมกันมากกว่านี้”
- ยังระบุด้วยว่าแท็ก
Reported-byไม่ได้สะท้อนการมีส่วนร่วมของ Ariel อย่างเหมาะสม
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
แม้จะไม่รับแพตช์ทั้งหมด ก็ควรให้ เครดิตแก่ Ariel Miculas มากกว่า
ปัญหาความปลอดภัยนี้มีโอกาสสูงว่าจะไม่มีใครแก้ หากเขาไม่ค้นพบและส่งแนวทางแก้ไขไป
ถ้า Michael อ่านแพตช์ของเขาแล้วแค่เปลี่ยนสไตล์บางส่วน ก่อนส่งในชื่อตัวเอง การไม่ให้เครดิตก็ถือว่าไร้จริยธรรม และต่อให้โค้ดแย่แค่ไหน มันก็ยังเป็นการร่วมมือกันอยู่ดี ถ้าโดนแบบนั้นก็คงไม่อยากทำงานร่วมกันอีก
แบบหลังอย่างน้อยยังเหลือ
Co-Authored-Byไว้ แต่หลังจากมีคนเอาโค้ดโปรเจกต์ของฉันไป dump ลง repository ของตัวเองโดยไม่มีประวัติ commit แล้วเรียกว่า “fork” ถึงได้รู้ว่าในฐานะผู้มีส่วนร่วม มันเป็นประสบการณ์ที่ค่อนข้างขมขื่นต่อให้โค้ดนั้นแย่ การแก้ไขที่ถูก refactor แล้วและถูก merge เข้าไปก็คงไม่มีอยู่ถ้าไม่มีโค้ดนั้น และคำว่า “เวอร์ชันของฉันดีกว่า” อาจฟังดูเหมือนดูแคลนมาก
แต่พอเห็นคำตอบที่ลิงก์ไปยังคำตอบจริงของ maintainer แล้ว ประโยคสุดท้ายนั้นก็ใช้ไม่ได้
แต่ในกรณีนี้ ผู้เขียนใกล้เคียงกับการเป็น ผู้เขียนร่วม ของแพตช์นั้น
ถ้าเทียบกับงานตีพิมพ์ทางวิชาการ ก็เหมือนส่ง preprint ให้ใครสักคน แล้วคนนั้นไปตีพิมพ์บทความในหัวข้อเดียวกัน โดยใส่ชื่อไว้แค่ในคำขอบคุณ แต่ไม่ใส่เป็นผู้เขียนร่วม
ที่นี่ไม่ใช่งานตีพิมพ์แต่เป็นการพัฒนา kernel แต่การระบุชื่อผู้เขียนยังสำคัญต่อประวัติวิชาชีพอยู่ดี
feedback เรื่องสไตล์และความสอดคล้องของโครงสร้างเป็นสิ่งจำเป็น แต่ maintainer ที่ยอดเยี่ยมคือคนที่ยอมรับเครดิตของผู้อื่นและทำให้งานไหลลื่นอยู่เบื้องหลัง
ตอนนั้นเมื่อ Ted Tso พอใจกับความถูกต้องของงานของผม เขาก็ใส่แพตช์เข้าไป และผมก็ไม่ได้เรียกร้องหรือได้รับเครดิต
สิ่งที่ผมสนใจมีเพียงการปรับปรุง kernel ไม่ได้สนใจการทิ้งชื่อไว้
หลายปีต่อมาชื่อผมไปอยู่ในรายชื่อ contributors จากงานอื่น แต่ไม่ว่าทางไหนผมก็ไม่ได้ใส่ใจ
Reported-by: Ariel Miculasอยู่ และดูถูกต้องดีแพตช์ของ maintainer ดีกว่า
fpidx < (PT_FPSCR - PT_FPR0)ในกรณี 32-bit*data = child->thread.fp_state.fpscr;ที่ใช้เมื่อfpidxอยู่นอกช่วงในฟังก์ชันputFPRINDEXที่ไม่จำเป็น ซึ่งลดรูปเป็น identity เมื่อTS_FPRWIDTHเป็น 1commit message ของแพตช์เดิมบอกว่า “ใน PPC32 สามารถสมมติได้ว่า
TS_FPRWIDTHเป็น 1” แต่ก็ยังใส่FPRNUMBER,FPRHALF,FPRINDEXเข้ามาแค่พบ array mismatch ที่แก้ได้ ไม่ได้แปลว่าต้องรับ แพตช์ที่มีบั๊ก เข้าไปตามเดิม
อย่างไรก็ตาม maintainer ควรยอมรับว่า Miculas ไม่ได้แค่รายงานเฉย ๆ แต่ได้ตรวจสอบจนพบ สาเหตุราก และยังทำเวอร์ชันแก้ไขแบบง่ายที่แทบเหมือนกันของตัวเองด้วย
Reported-byไม่แม่นยำพอที่จะสื่อ nuance ว่าบุคคลนั้นตรวจสอบอย่างละเอียดและระบุสาเหตุได้แล้วสำหรับผู้มีส่วนร่วมรายใหม่ โปรเจกต์ต่าง ๆ มักทำแบบนั้น และนั่นคือวิธีที่ถูกต้อง
มันเป็นกระบวนการสอนคนและช่วยให้เขาปรับตัว แต่ถ้าไปทำงานใหม่เองเสียเลย ก็ทำลายแรงจูงใจในการ contribute และตัดโอกาสในการเรียนรู้ไปด้วย
การเขียนเวอร์ชันที่สองย่อมง่ายกว่าเสมอ
การเรียกสิ่งนี้ว่าเป็นการแก้ง่าย ๆ แสดงว่าไม่เข้าใจปริมาณงานที่ต้องใช้ในการแก้บั๊กในการพัฒนาซอฟต์แวร์
ในที่นี้ Michael เองก็ยอมรับว่าตอนแรก reproduce ไม่ได้ และเพิ่งยืนยันได้ภายหลัง
นี่แสดงให้เห็นชัดถึงปริมาณงานที่ OP ทุ่มให้กับ การ debug และการแก้ไข และการขโมยงานนั้นไปไม่ใช่เรื่องถูกต้อง
ในต้นฉบับบอกว่าเขาอยากให้แพตช์ได้รับการยอมรับ ได้เครดิต และกลายเป็น contributor ของ kernel และยินดีส่งเวอร์ชันถัดไปตาม feedback
maintainer แค่ checkout โค้ดของ OP แล้วแก้ตามที่ต้องการ จากนั้นใช้เวลาประมาณ 2 นาทีเพื่อ commit ในฐานะ ผู้เขียนร่วม ก็พอ
แบบนั้นการแก้ไขที่ดีที่สุดจะถูก merge และงานของคนอื่นก็ได้รับการยอมรับ
โดยเฉพาะเมื่อ OP แสดงชัดเจนว่าอยากได้รับเครดิต นั่นจึงเป็นทางเลือกที่ดีที่สุด
แต่ดูเหมือน maintainer ของ repository แบบนี้มักพลาดเรื่องมารยาททางสังคมอยู่บ่อย ๆ จึงไม่น่าแปลกใจ
PR มักไม่ถูกรับด้วยหลายเหตุผล แต่ผมไม่ใส่ใจ
ผมส่ง PR เพื่อให้โค้ดเผยแพร่อยู่ตรงนั้น และไม่ได้ใช้เวลาทำให้มัน “ดี” พอที่จะ merge
แค่ส่งไว้ตามนั้น ถ้าใครชอบพอ คนนั้นก็จัดการขั้นตอนต่อเอง
บางอันถูก merge ตามเดิม บางอันเจ้าของ repository แก้นิดหน่อยแล้ว merge
ผมไม่ได้เขียนโค้ดโอเพนซอร์สเพราะเกียรติยศหรือความนิยม แต่ทำเพราะชอบ
คิดถึงยุค 80 และ 90
เคอร์เนล Linux ไม่ใช่รางวัล และแม้จะเห็นใจ OP แต่ชุมชนควรเลือกแนวทางแก้ปัญหาที่ดูแลรักษาได้ง่ายกว่าจากเวอร์ชันที่ชุมชนเสนอ
ดังนั้น maintainer จึงยังอยู่ในขอบเขตอำนาจของตน
แต่การให้ เครดิต แก่ผู้ที่มีส่วนร่วมในการแก้ไขนั้นทำได้ง่ายมาก
ใน Node.js เราให้เครดิตใน release notes และเมื่อหยิบบางส่วนของงานจาก PR มาปรับแก้ เราก็พยายามเพิ่ม
Co-Authored-By:เมื่อดูแลรักษามานาน เครดิตอาจสำคัญกับตัวเองน้อยลง จึงลืมได้ง่ายว่าสิ่งนี้สำคัญมากสำหรับผู้ร่วมให้ข้อมูลรายใหม่
ในกรณีนี้ การที่ไม่ใส่ใจมากพอในการแบ่งปันเครดิต ทั้งที่มันสำคัญกับ OP และสมควรได้รับ ถือเป็นความสูญเสียทั้งต่อ OP และต่อส่วนงาน Linux นั้น
นั่นไม่ใช่วิธีที่โปรเจกต์ซึ่งพึ่งพาความพยายามของชุมชนจะยืนยาวได้
ผมเคยคิดว่าโปรเจกต์ที่ใหญ่และได้รับความเคารพอย่างเคอร์เนล Linux น่าจะมีคนที่รู้จักดูแลผลประโยชน์สูงสุดของโปรเจกต์ พร้อมกับเคารพผู้ร่วมให้ข้อมูลรายใหม่ด้วย
คงไม่มีใครเสนอให้รับแนวทางแก้ปัญหาที่ไม่ดีที่สุดเพียงเพราะเป็นผู้ร่วมให้ข้อมูลรายใหม่
วิธีที่ถูกต้องคือรีวิวแพตช์ อธิบายว่าอะไรเป็นปัญหาและเพราะอะไร แนะนำว่าควรเขียนใหม่อย่างไร และถ้าจำเป็นก็ร่วมเขียนส่วนนั้นด้วยกันจนกลายเป็น ผู้เขียนร่วม
แบบนั้นจึงจะเกิดกระแสผู้ร่วมให้ข้อมูลที่สนใจต่อไปในอนาคต
Reported-Byในเอกสารของเคอร์เนลมีการกำหนด
Suggested-byไว้เป็นหนึ่งในธรรมเนียมการใช้แท็กแท็ก
Suggested-by:ระบุว่าบุคคลนั้นเป็นผู้เสนอไอเดียของแพตช์ และรับประกันเครดิตสำหรับไอเดียนั้นโดยเฉพาะถ้าไอเดียนั้นไม่ได้ถูกโพสต์ในฟอรัมสาธารณะ ก็ระบุว่าไม่ควรเพิ่มแท็กนี้โดยไม่ได้รับอนุญาตจากผู้เสนอ
ยังเขียนไว้ด้วยว่า หากให้เครดิตแก่ผู้แจ้งไอเดียอย่างจริงใจ พวกเขาก็มีแนวโน้มจะกลับมาช่วยอีกในอนาคต
ในสถานการณ์นี้
Suggested-byอาจเหมาะสมกว่ามันสื่อได้ดีกว่าว่าเขาพบแนวทางแก้ปัญหาแล้ว แต่เพราะไม่คุ้นเคยกับโปรเจกต์ จึงไม่ได้คงไวยากรณ์ที่ถูกต้องของแพตช์ไว้
อ้างอิง: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
ฝั่งหนึ่งอยู่ใน
ifdefนอกifส่วนอีกฝั่งอยู่ในคำสั่งifด้านในเท่านั้น และเป็น ความต่างด้านสไตล์ ไม่ใช่ความต่างทางเทคนิคถ้าเป็นเช่นนั้น ผู้เขียนก็ทำไปมากกว่าการแค่ “เสนอ” ไอเดียแพตช์มาก
เขาดีบัก issue และเขียนแพตช์ทั้งหมดแล้ว เพียงแต่แพตช์ที่ถูกรับมีการเปลี่ยนแปลงเล็กน้อยหนึ่งจุด
1: https://news.ycombinator.com/item?id=37672558
สำหรับ issue ด้านความปลอดภัย ความเร็วและความถูกต้องสำคัญกว่ารูปแบบ และ maintainer ของเคอร์เนลก็จัดการได้ถูกต้องแล้วในแง่ที่ให้เครดิตด้วย
Reported-bySuggested-byอาจดีกว่าเล็กน้อยก็จริง แต่ไม่ใช่สิ่งที่ OP ต้องการ และดูเหมือน OP ต้องการป้ายว่าเป็น “ผู้ร่วมให้ข้อมูลเคอร์เนล” จากแพตช์เล็กมากชิ้นหนึ่งเมื่อดูปฏิกิริยาบางส่วนในเธรดนี้แล้ว ก็หวังว่าบางคนจะไม่ต้องไปบริหารนักพัฒนาระดับจูเนียร์หรือระดับกลางเป็นพิเศษ
ถ้าในทีมมีจูเนียร์ที่กระตือรือร้น และส่ง PR ที่ช่วยแก้บางประเด็นได้แต่คุณภาพยังไม่ถึง การดุว่า “ยังดีไม่พอ” แล้วทิ้งโค้ดไปเขียนใหม่เอง คือการรับมือที่แย่ที่สุด
มันบั่นทอนกำลังใจ ทำให้ทั้งเขาและคุณเสียเวลา ไม่ได้เรียนรู้อะไร ทำให้ครั้งหน้าปรับปรุงหรือมีส่วนร่วมอย่างมีความหมายไม่ได้ และยังทำให้ไม่อยากขอความช่วยเหลือหรือมีส่วนร่วมโดยสมัครใจด้วย
ต่อให้เขากระโดดเข้าไปในส่วนโค้ดที่ซับซ้อน ก็ยังมีวิธีปฏิสัมพันธ์ที่ดีกว่านี้
จูเนียร์ในทีมมีความคาดหวังว่าจะอยู่ไปอีกระยะหนึ่ง และผ่านการสัมภาษณ์จนตรวจสอบทักษะพื้นฐานได้ในระดับหนึ่งแล้ว จึงเชื่อถือศักยภาพในการเติบโตได้
คนสุ่ม ๆ บนอินเทอร์เน็ตไม่มีพันธะว่าต้องอยู่ต่อ และการแก้แบบ “แวะมายิงแล้วไป” แบบนี้ส่วนใหญ่ก็ไม่อยู่ต่อ
เราไม่รู้ว่าคนนั้นมีความสามารถจริง ๆ แค่ไหน หรือจะตอบสนองต่อคำขอให้แก้อย่างไร
หนึ่งในเรื่องที่น่าหงุดหงิดที่สุดจากมุมมองการจัดการ คือการที่ใครสักคนเอาคนสุ่ม ๆ มาใส่ไว้ในสายงานที่ผมต้องดูแล แล้วทำให้ผมต้องรับผิดชอบผลงานของคนนั้น
ทีนี้ลองนึกภาพว่ามีคนบนอินเทอร์เน็ตที่รู้สึกว่าตัวเองมีสิทธิ์เรียกร้อง ใช้เวลาหลายวันทำการแก้ไขคุณภาพต่ำขึ้นมา แล้วผมควรต้องโค้ชเขาเหมือนเป็นผู้จัดการของเขา อุปมานี้จึงไม่สมเหตุสมผล
เมื่อก่อนเคยสงสัยว่าทำไมการโฮสต์โปรเจกต์บน GitHub แล้วมี PR ที่ไม่ต้องการถึงกลายเป็นเรื่องวุ่นวาย แต่ตอนนี้เข้าใจแล้ว
การที่ถ้าไม่อยากรับมือกับ PR แบบสุ่ม ๆ แล้วถูกตำหนิว่าเป็น “ผู้จัดการแย่ ๆ ที่บั่นทอนกำลังใจและทำให้คนอื่นเสียเวลา” นั้นเป็นความรู้สึกว่าตัวเองมีสิทธิ์เรียกร้องที่เกินไป
ตัวอย่าง: https://news.ycombinator.com/item?id=25940799
การเป็นมืออาชีพส่วนหนึ่งคือการเรียนรู้ที่จะแยกตัวเองออกจากผลงาน และเข้าใจว่าเพื่อนร่วมงานไม่ได้มีแผนร้ายจะขัดขวางเรา
ทุกคนเคยมีโปรเจกต์ที่ทำมาหลายเดือนถูกยกเลิก และเคยได้รับคอมเมนต์แรง ๆ ใน code review
การยอมรับและเรียนรู้จากเรื่องแบบนั้นเป็นหน้าที่ของมืออาชีพ
แน่นอนว่าคนที่พูดตรงและหยาบคายก็ต้องเรียนรู้เหมือนกันว่าท่าทีแบบนั้นทำลายความสัมพันธ์จำนวนมาก
เราไม่ใช่ศิลปิน แต่เป็นมืออาชีพ
ถ้าวิศวกรโยธาจูเนียร์ออกแบบสะพานที่มีข้อบกพร่องด้านโครงสร้าง แล้วซีเนียร์บอกว่า “ขอโทษนะ แต่นี่คงกู้ยากแล้ว ต้องทำใหม่ทั้งหมด” ซีเนียร์ก็ไม่ได้ผิด
เราคงไม่อยากขับรถบนสะพานที่เปราะบางเพียงเพื่อรักษาอัตตาของจูเนียร์
คอมเมนต์ที่ดูเหมือนไม่ค่อยมีประสบการณ์ดูแลโปรเจกต์โอเพนซอร์สขนาดใหญ่ มักมอง maintainer ว่าโหดร้ายเป็นพิเศษ
ถ้าเคยดูแลโปรเจกต์โอเพนซอร์สเล็ก ๆ จะรู้ว่าการรับ PR จากคนสุ่ม ๆ เป็นงานเยอะ และบ่อยครั้งใช้เวลามากกว่าทำเอง
เวลาที่ต้องใช้ไปกับการรีวิวโค้ดอย่างละเอียด สื่อสารกับผู้ร่วมพัฒนาเพื่อแก้ปัญหา และทำให้คุณภาพกับธรรมเนียมสอดคล้องกับที่คาดหวังนั้นสูงมาก
จูเนียร์ในที่ทำงานผ่านการสัมภาษณ์มาแล้ว แต่ในกรณีนี้คือคนแปลกหน้าแบบสุ่ม ๆ ที่ขอให้เปลี่ยนแปลง
เมื่อ PR ถูกปฏิเสธก็ย่อมเสียใจ แต่เข้าใจมุมมองของทั้งสองฝ่าย
เมื่อดูบทสนทนาของ maintainer แล้ว ก็ไม่ได้ดูใจร้ายหรือหยาบคายเป็นพิเศษ
แทบให้ความรู้สึกเหมือนเธรดแย่ ๆ ใน LKML
คนนั้นทำ 95% ของงาน อย่างแท้จริง แต่กลับถูกวิจารณ์ว่าอยากได้รับการยอมรับในเครดิตนั้น
ไม่เข้าใจเลยว่าทำไมถึงเป็นแบบนั้น
เมื่อเทียบแพตช์ทั้งสอง จะเห็นความต่างชัดเจน
การมีส่วนร่วมในบทความที่ลิงก์ไว้เปลี่ยนพฤติกรรมของทั้งสองกิ่งของ
if...elseแต่การมีส่วนร่วมสุดท้ายเปลี่ยนเฉพาะพาธในกิ่งifmaintainer น่าจะมีเหตุผลที่เปลี่ยนโค้ด
ถึงอย่างนั้น การแก้ไขจริงก็แทบถูกคัดลอกมาเกือบ 100% ดังนั้นการให้ เครดิต แก่ผู้เขียนแพตช์ต้นฉบับจึงเหมาะสม
ผลลัพธ์เดิมคือบนสถาปัตยกรรม PPC32 ไม่มีทั้ง
flush_fp_to_threadและไม่มีเงื่อนไขelseแพตช์สุดท้ายเรียก
flush_fp_to_thread(child);แล้วจัดการตามว่าเป็นCONFIG_PPC32หรือไม่ภายในการตรวจสอบช่วงของfpidxจากนั้นถ้าอยู่นอกช่วงก็ใส่ค่าให้fpscrดังนั้นจึงมีความแตกต่างจริงระหว่างสองวิธีแก้
บอกไม่ได้ว่าฝั่งไหนถูกหรือดีกว่า แต่ชัดเจนว่าผลลัพธ์ต่างกัน
มันอาจบ่งบอกถึงความไม่ชำนาญใน C
การดูแล codebase ขนาดใหญ่ ครึ่งหนึ่งคือการดับไฟ และอีกครึ่งหนึ่งคือ การหลีกเลี่ยงการชนกันของชื่อ
แพตช์นั้นค่อนข้างต่างกัน และผมน่าจะเก็บไว้ที่ไหนสักแห่งเพื่อให้เอามาแสดงได้
นี่เป็นส่วนหนึ่งที่พบได้ทั่วไปของการมีส่วนร่วมกับเคอร์เนล
หลายครั้งวิธีที่กระชับที่สุดในการสื่อสารปัญหาคือแพตช์ จึงส่งแพตช์ไป และควรตั้งความคาดหวังไว้ทางที่ว่าเขาอาจไม่ใช้แพตช์นั้น
แค่นึกออกก็มีเรื่องแบบนี้เกิดกับผมอย่างน้อยสามครั้ง [1][2][3]
พูดตรง ๆ ผมไม่เคยคิดจะโกรธเลย เพราะเป้าหมายหลักของผมคือการแก้บั๊ก และผมก็ดีใจที่มันถูกแก้
ถ้าจะให้คำแนะนำ OP อย่างจริงใจ ผมว่าควรลบบล็อกโพสต์นี้เสีย คุณจะเสียใจภายหลัง
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
ผมค่อนข้างตกใจเมื่อเห็นชื่อของอีกคน
ในโปรเจกต์โอเพนซอร์ส เรื่องแบบนี้เกิดขึ้นตลอด และสุดท้ายก็แค่ทำให้หมดแรงอยากมีส่วนร่วมเพิ่ม
ปีที่แล้วผมรับอิสชูที่เปิดค้างมาหลายปีมาทำ สร้าง PR แก้โค้ดทดสอบ และยังทำงานแยกเพื่อแก้ปัญหาบิลด์ด้วย
ผู้ดูแลเอาไปเฉพาะ PR ที่แก้ปัญหาบิลด์ ส่วนอิสชูเดิมก็ปล่อยผ่านไปเฉย ๆ
ไม่มีทางเลยที่ผมจะกลับไปใช้เวลาเพื่อมีส่วนร่วมกับโปรเจกต์นั้นอีก
เปิด PR แล้วได้รับคอมเมนต์ขอให้แก้ไข
พออีกไม่กี่วันต่อมามีเวลาจะแก้ กลับพบว่าถูกปิดไปแล้วโดย PR อื่นจากคนที่มีส่วนร่วมบ่อย
พอดู PR นั้น โค้ดแทบจะเหมือนของผม เปลี่ยนแค่ชื่อตัวแปรตัวเดียว และได้รับการอนุมัติทันทีตามมาตรฐานรีวิวแบบ “เพื่อนกัน”
พอดูโปรไฟล์ของคนนั้น ก็พบว่าแทบทุกการมีส่วนร่วมคือการคัดลอกโค้ดของคนอื่น
ผมพยายามช่วยจัดให้เข้ากับส่วนที่เหลือของ codebase ซึ่งนี่แหละเป็นส่วนที่ยากที่สุด
เพราะนักพัฒนาส่วนใหญ่อยากยัดสิ่งที่ตัวเองแก้เข้าไปเลย มากกว่าจะเรียนรู้ธรรมเนียมของโปรเจกต์ก่อน
ถึงอย่างนั้น ถ้าโค้ดโดยรวมถูกทาง และหลัง merge แล้วผมใช้เวลาปรับอีกประมาณ 15 นาทีพร้อมเพิ่มเทสต์อีกนิดหน่อยก็พอ ผมก็รับ
กรณีนี้ก็ดูเหมือนสถานการณ์แบบนั้น และผู้ดูแลควรทำแบบนั้น
ผู้มีส่วนร่วมได้เครดิต ส่วนผู้ดูแลก็ใช้เวลาไม่กี่นาทีเก็บงานเท่าที่จำเป็นให้พอ upstream รับได้ ทุกฝ่ายก็น่าจะพอใจ
คำพูดว่า “เวอร์ชันของผมดีกว่า” นั้นฟังดูหยิ่งและไม่เป็นมืออาชีพมาก ไม่ว่ามันจะดีกว่าจริงหรือไม่ก็ตาม
ถ้าแก้ไม่ได้มา 6 ปีนับจากที่มีรายงานอิสชูครั้งแรก ก็ควรยอมรับว่าหากไม่มีการมีส่วนร่วมของคนนั้น การแก้ของคุณก็คงไม่เกิดขึ้นเช่นกัน
การเห็น “แนวทางแก้” แล้วเอาการแก้นั้นไปใช้ แทบจะใกล้เคียงกับการขโมยอยู่แล้ว
ผู้คนมักมองเป็นเรื่องส่วนตัวเมื่อโค้ดของตัวเองไม่ถูกรับ หรือถูกเขียนใหม่ แต่พลาดไปว่าการเขียนโค้ดเป็นเพียงส่วนเล็ก ๆ ของการดำเนินโปรเจกต์
ปกติผมจะดูรายงานบั๊กและ merge request เพื่อประเมินว่าแพตช์จะถูกปฏิบัติอย่างไร
ในโปรเจกต์ที่ดูไม่น่ามีส่วนร่วมด้วย ผมก็ปล่อยการแก้บั๊กจำนวนมากไป และเคอร์เนล Linux เมื่อปี 2003 ก็เป็นตัวอย่างหนึ่ง
บางโปรเจกต์ก็เป็นแบบนั้นเอง ไม่เข้าไปยุ่งจะดีกว่า และส่วนใหญ่ก็เสียเวลาเปล่า
ตอนนี้หลังการปฏิวัติ AI มีการละเมิดไลเซนส์โอเพนซอร์สอย่างกว้างขวาง ตั้งแต่นั้นมาผมจึงไม่ได้ส่งโค้ดโอเพนซอร์สอีก และต่อไปก็จะไม่ส่ง
ผมเข้าใจความเป็นพิษในที่นี้ได้ยากจริง ๆ
คำพูดทำนองว่า “ไม่ควรทำเพื่อการยอมรับ ดาว รางวัล หรือเรซูเม่” ฟังดูบ้าบอมาก
คนที่พูดแบบนั้นมีงานทำกันไหม? ถ้ามี เพื่อให้สอดคล้องกันก็ควรทำงานฟรีล้วน ๆ
เงินเดือนก็เป็น รูปแบบหนึ่งของการยอมรับ ต่อการมีส่วนร่วมเช่นกัน
ส่วนตัวแล้ว แม้วิธีแก้สุดท้ายจะต่างจากที่เสนอไป แต่ถ้ามันต่อยอดจากการค้นพบวิธีแก้เดิม การเพิ่มผู้ร่วมเขียนก็เป็นเรื่องเล็กมาก
ผู้เขียนมีเหตุผลที่สมควรจะบ่นเรื่องนี้ และนี่คงไม่ใช่ครั้งแรกหรือครั้งสุดท้ายที่ใครสักคนรู้สึกว่าการมีส่วนร่วมของตนไม่ได้รับการยอมรับ
ต่อให้ตัวแพตช์ด้อยกว่า แต่ความพยายามในการดีบักไม่ได้ด้อยเลย
ในการจ้างงาน นายจ้างกับลูกจ้างตกลงกันว่าจะทำงานแลกกับค่าตอบแทน
ถ้าคุณเดินเข้าไปในบริษัทหนึ่งโดยไม่บอกล่วงหน้า แล้วเริ่มทำงานที่ไม่มีใครขอให้ทำ แทบไม่มีใครจะอ้างว่าตนมีสิทธิได้รับค่าตอบแทน
อุปมาที่ตรงกับสิ่งที่เกิดขึ้นกับ OP มากกว่าคือแบบนี้
การตอบโต้ในทำนองว่า “ขอโทษนะ แต่เวอร์ชันของฉันดีกว่า ถ้าอยากเป็นผู้มีส่วนร่วมในเคอร์เนล Linux ก็มี issue นี้ที่คุณไปแก้ได้” เป็นวิธีที่ยอดเยี่ยมในการทำให้ใครสักคนไม่อยากช่วยอีก และยังบั่นทอนแรงจูงใจของคนอื่น ๆ ด้วย
ผู้ดูแลบอกว่าไม่สามารถ reproduce crash ด้วย
gdbserverได้ แต่มี test case ที่แสดงบั๊กอยู่ จึงตรวจสอบและทดสอบการแก้ไขแล้ว และเขียนว่า “ขอบคุณสำหรับ patch แต่ผมอยากแก้มันด้วยวิธีที่ต่างออกไป ช่วยลอง patch ด้านล่างแล้วดูให้หน่อยได้ไหมว่าบั๊กได้รับการแก้หรือยัง?”https://lists.ozlabs.org/pipermail/linuxppc-dev/2022-June/24...
ยังมีคอมเมนต์ review อื่น ๆ ที่ไม่ได้ถูกกล่าวถึงด้วย
เนื้อหาคือไม่แน่ใจว่ามีข้อดีอะไรกับ macro ที่มีไว้สำหรับ PPC32 เท่านั้น, ควรหลีกเลี่ยง
#ifdefให้มากที่สุดเท่าที่ทำได้ และ patch ของ Michael เข้าใจง่ายกว่าhttps://lists.ozlabs.org/pipermail/linuxppc-dev/2022-June/24...
OP กำลังยัดคำพูดใส่ปากอีกฝ่ายแล้วโกรธกับมัน ซึ่งไม่ใช่กลยุทธ์ที่ดี โดยเฉพาะในการสื่อสารผ่านข้อความ
OP ทำให้บทสนทนาดูเหมือนหยาบคาย แต่ความจริงไม่ใช่อย่างนั้น