Pidgin: Random Crash on Windows (GDI Objects Leak)

ผมใช้ Pidgin เล่น Google Talk มาหลายเดือนแล้วเนื่องจากเบื่อ Google Talk Client ที่แสนเก่าและไร้ซึ่งลูกเล่นใดๆ แต่ Pidgin ยังมีปัญหาหลักๆที่กวนใจอยู่เสมอคือ มันชอบ crash เอามากๆ crash วันหนึ่ง 3-4 ครั้งได้ จนตอนนี้เรียกได้ว่ามี sense รู้สึกได้ว่ามันกำลังจะ crash

อาการที่เห็นคือตำแหน่งของข้อความที่คุยจะเลื่อนแล้วไม่ค่อยตรง บางทีมี font เกยๆกัน หนักเข้าหน่อยหน้าต่างจะเริ่มเป็นสี่เหลี่ยม mosaic สีน้ำเงินแดงเต็มไปหมด หลังจากนั้น 2-3 วินาทีก็จะมีเสียงอันน่าสะพรึงกลัวดังขึ้น พร้อมกับปุ่ม OK ให้เรากดยอมรับแบบห้ามมีข้อโต้แย้งใดๆทั้งสิ้น

ขอบ่น

หลังจาก format เครื่องไปเมื่อวานด้วย ความหวังว่าปัญหานี้จะหายไป ลืมบอกไปว่า ก่อน format ก็มีบางโปรแกรมที่ crash บ่อยเหมือนกัน เลยนึกว่าเป็นที่ Windows  แต่แล้วมันก็ไม่หายครับ มันออกลายอีกครั้งเมื่อบ่ายวันนี้ด้วยการ crash ติดต่อกัน 3 รอบขณะผมนั่งค้น chat logs อยู่

ยังดีที่สาเหตุการ format ครั้งนี้จริงๆแล้วไม่ได้มาจาก pidgin ไม่งั้นผมคงเซ็งเป็ดที่ต้องมานั่ง format ลง Windows ลงโปรแกรม เสียเวลาไป 3 ชั่วโมงแล้วไม่ได้อะไรขึ้นมา สาเหตุจริงๆที่ format คือ Microsoft SQL มันรันไม่ได้ แล้วผมต้องใช้สอบสัปดาห์หน้า ซึ่งนั่นไม่เกี่ยวกับ entry นี้จึงไม่ขอเล่าต่อ

ถึงยังไงผมหมดความอดทนแล้วล่ะ ต้องหาทางแก้ปัญหานี้ให้ได้ ไม่งั้นก็จะกลับไปใช้ Google Talk Client ตัวเดิมอย่างถาวรแล้ว ด้วยความโชคดีบางอย่างทำให้การ crash ครั้งนี้มันแสดงรายละเอียดและสาเหตุที่พังด้วย ทำให้รู้ว่าต้นเหตุมาจาก libcairo-2.dll ก็เลยลองไปถามอากู๋เพื่อนยากจนได้คำตอบมามากมาย และได้รู้ว่ามีผู้ร่วมชะตากรรมกับเรามิใช่น้อย

สาเหตุที่ crash

แหล่งบั๊กที่ได้ข้อมูลหลักๆมาคือ GNOME #543209 และ Pidgin #5662 สรุปปัญหาได้ว่ามันเกิดขึ้นใน GTK+ โดยเมธอด gdk_window_begin_paint_region() ส่งค่า NULL ไปให้ cairo_surface_set_device_offset() แทนที่จะเป็น GDI handle ทำให้ cairo มัน crash ทันที

ซึ่งพอไล่ตามต้นสายปลายเหตุแล้วก็พบว่าที่มันส่งค่า NULL ไปนั้นเป็นเพราะไม่สามารถสร้าง GDI handle อันใหม่ขึ้นมาได้ เนื่องจากจำนวน GDI handle ที่มีมันเยอะเกินกว่าที่ Windows อนุญาต

ด้วยความที่ Pidgin เป็นนักสร้าง GDI ตัวพ่อ ใช้ๆไปแปปเดียวจำนวน GDI ก็พุ่งทะลุ 2000 กว่าอันแล้ว มันเลยเกิดปัญหา GDI objects leak ขึ้น คือถ้ายิ่งใช้ไปนานๆ จำนวน GDI handle ก็จะเพิ่มขึ้นเรื่อยๆ ซึ่งพอถึงจุดที่ไม่สามารถสร้าง GDI handle ใหม่ขึ้นมาได้ มันเลยได้ NULL มาแทนที่จะเป็น GDI handle ที่ผมสงสัยคือเท่าไหร่ล่ะถึงเรียกว่าเยอะเกิน?

ผมลองไปค้น MSDN หัวข้อ GDI Objects เขากล่าวไว้ว่า ตามทฤษฎีแล้ว Windows XP สามารถรองรับ GDI ได้ถึง 65,536 handles แต่จะถูกลิมิตไว้จาก registry key อันหนึ่งคือ

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\GDIProcessHandleQuota

ว่าแล้วผมก็ไปเปิดดูของผมบ้าง ไล่ๆไปจนเจอ key ที่ว่านั่น ชัดเจนเลยครับ เป็นไงล่ะ…

10k !!!

Oh! Shit

ชัดเจนครับ มัน Limit ไว้แค่ 10,000 อันเท่านั้น แล้วดู pidgin.exe ตัวน้อย แค่เปิดหน้าต่าง Log กดไปมา 20 กว่าไฟล์มันก็บริโภคไปซะขนาดนี้แล้ว ไม่แปลกใจเลยที่มัน crash วันละ 3-4 ครั้ง

ยิ่งไปกว่านั้นคือ ยิ่ง GDI เยอะเท่าไร โปรแกรมก็จะบริโภคหน่วยความจำมากขึ้นเท่านั้น ทำให้ Pidgin กินแรมทะลุไปถึง 100+ MB ได้อย่างรวดเร็วซึ่งไม่ใช่เรื่องดีแน่ๆ (แต่ปกติก็ไม่ค่อยถึงหรอกนะ เพราะมันจะ crash ไปก่อน)

วิธีแก้ล่ะ

บ่นมาเยอะแล้วมาฟังข่าวดีกันบ้างดีกว่า คือว่า pango ตัวล่าสุดแก้ปัญหา GDI object leak นี่ไปเรียบร้อยแล้ว ทางแก้คือไปโหลด GTK+ ตัวใหม่มาลงทับของเดิม ขั้นตอนก็ตามนี้

  1. ปิด Pidgin และโปรแกรมที่ใช้ GTK+ ให้หมด
  2. ไปโหลด GTK+ for Windows เข้าไปแล้วเล็งๆหาหัวข้อ All-in-one bundle แล้วจิ้มลิงค์ bundle
  3. extract ไฟล์ทั้งหมดลงในโฟลเดอร์ GTK โดยปกติแล้ว Pidgin จะลงไว้ที่ C:\Program Files\Common Files\GTK\2.0 โดยทับไฟล์เดิมให้หมด
  4. เปิด Pidgin ขึ้นมาใหม่ได้เลย

แถมนิดนึง รูป Process หลังจากลง GTK+ ใหม่แล้ว

New Pidgin!

แหล่งข้อมูล

Comments

comments

2 thoughts on “Pidgin: Random Crash on Windows (GDI Objects Leak)”

  1. นาย ลง windows มันช้านะ ลง Ubuntu สิ เร็วสะใจ – -” ได้ของเกือบครบด้วย…

Leave a Reply

Your email address will not be published. Required fields are marked *