Friday, January 28, 2011

ประสบการณ์การ submit patch ครั้งแรก (แต่ไม่สำเร็จ)

ปีที่แล้วผมได้งานเขียนโปรแกรมชิ้นนึงครับ ตอนนั้นภาษาที่ผมใช้ก็เลือกใช้ python (เหตุผลไม่มีอะไรมาก แค่อยากลองศึกษาภาษานี้ดู) โปรแกรมที่เขียนจะมีฟังก์ชันการทำงานอยู่อันนึงครับ ที่มันจะเปิด https connection แล้ว get เนื้อหาเว็บมาดู

โปรแกรมที่เขียนนี้ก็ติดตั้งให้เครื่องลูกค้าไปหลายเครื่องทีเดียว และก็ดูเหมือนไม่มีปัญหาอะไร แต่ปรากฎว่าอาทิตย์ที่แล้ว พี่ที่ทำงานเค้าลอง monitor เครื่องลูกค้าดู ปรากฎว่ามันมี https connection เปิดค้างอยู่มากมายหลายสิบ เลยถามผมว่ามันถูกต้องรึปล่าว ผมเห็นแล้วก็ค่อนข้างอึ้งเล็กน้อย นี่ตรูนู้บขนาดลืมปิด connection เลยเหรอฟระ

แต่หลังจากอ่านโค้ดของตัวเองดู ผมก็เห็นว่าสั่งปิด connection แล้วนี่หน่า แล้วทำไมตรวจสอบ socket ดูถึงยังเห็นมันเปิดค้างอยู่ หลังจากพยายามแก้โค้ดอยู่ซักพักก็ไม่สำเร็จ เลยลองเช็ค bug tracker ของ python ดู ปรากฎว่ามีคนเคยเปิด issue นี้แล้วครับ ตั้งกะ python 2.3 แล้วก็ปิดเป็น won't fix ไปแล้วด้วย (ผมใช้ python 2.6 อยู่ครับ)

อ่านจบตอนนั้นคิดไงไม่รู้อยากลองไล่บั๊กดู (library ของ python มันมีเป็นโค้ดติดตั้งอยู่ในเครื่องอยู่แล้วครับ ไม่ต้องโหลดมาเพิ่ม) ไล่ไปไล่มาก็เจอส่วนที่คิดว่าน่าจะเป็นปัญหา เหมือนว่าจะเช็ค condition ผิด ไปตอนสั่งปิด SSL socket ลองแก้โค้ดดูก็ปรากฎว่าทำงานได้ถูกต้อง (มั้งนะ ฮ่าๆๆ)

พี่ที่ทำงานก็ยุให้ลอง submit patch ไปดู ผมก็เลยลองโหลด python 2.7 มา หลังจากเช็คดูก็เห็นว่าตรงโค้ดส่วนนั้นยังเป็นเหมือนเดิม ผมก็เลยเปิด issue แล้วก็ submit patch ของผมไป แต่หลังจากคุยตอบโต้ไปมาก็มีคนมาบอกว่าให้ผมลอง python 2.7 ดู บั๊กนี้น่าจะโดนแก้ไปแล้ว ซึ่งปรากฎว่ามันก็โดนแก้ไปแล้วจริงๆด้วย ฮ่าๆๆ แต่ก็ไม่รู้ว่าไปแก้อีท่าไหนเหมือนกัน ทำไมโค้ดตรงส่วนที่ผมคิดว่ามันเป็นปัญหาถึงยังเหมือนเดิม เหอๆ

ก็ปรากฎว่า patch ที่ส่งไปก็ปล่าวประโยชน์ T_T

สำหรับ issue ที่ผมเปิดอยากเข้าไปดูก็ไปดูได้ตามลิงค์นี้นะครับ http://bugs.python.org/issue10993

Saturday, June 26, 2010

ภาษาโปรแกรมที่อยากเขียนเป็น

อยากเขียนเป็นและเก่งๆด้วย
  1. C
  2. C++
  3. Java
  4. perl
อยากเขียนเป็นเฉยๆ
  1. Python
  2. OCaml
  3. PHP
  4. javascript

Wednesday, June 23, 2010

How to change resolver configuration file?

Q: How to change resolver configuration file?
A: I don't know.

ตรงนี้ขอเกริ่นนำกับบ่นๆๆๆๆ ก่อนนะครับ
อยากรู้วิธีแก้ path ของไฟล์คอนฟิก ข้ามไปอ่านข้างล่างได้เลยครับ
เมื่อประมาณต้นปีผมต้องเขียนโปรแกรมนึงให้มันไปเปลี่ยน dns server ของระบบ (FreeBSD) ที่โดนตั้งไว้ ปัญหาคือตอนที่ FreeBSD จะทำการ nslookup ไปที่ dns server มันจะอ่านไฟล์คอนฟิกนึงว่า dns server ของเราคือเครื่องไหน ไฟล์นั้นก็คือ /etc/resolv.conf ซึ่งมันจะอ่านทุกครั้งที่เราจะ nslookup!!! (ใส่เครื่องหมายตกใจทำไม อ้าว ไม่ตกใจเหรอครับ เพราะผมไม่รู้มาก่อน นึกว่ามันจะทำการโหลดค่ามาเก็บไว้ตอนบู๊ทเครื่องทีเดียว ไม่คิดว่ามันจะอ่านไฟล์ใหม่ทุกครั้ง)

เนื่องจากว่านโยบายในการเขียนโปรแกรมครั้งนั้นมีอยู่ว่า โปรแกรมของผมจะไม่แตะต้องไฟล์ใน /etc เพราะมันเป็นไฟล์ของระบบ ถ้าเกิดทำอะไรเสียหายไปเดี๋ยวจะเดือดร้อน (/etc ของ appliance ในความคิดผมควรจะเป็น read-only) ซึ่งจากประสบการณ์ที่ได้แตะเซอร์วิสของ FreeBSD มาบ้าง เซอร์วิสส่วนใหญ่เราสามารถระบุได้ว่าจะให้มันไปอ่านไฟล์คอนฟิกที่ไหน (ระบุได้จากหลายๆทาง เช่น environment variable ฯลฯ) หรือไม่ก็สามารถคอนฟิกในไฟล์คอนฟิกให้มัน include ไฟล์คอนฟิกอื่นเพิ่มเข้าไปได้ เราก็จะได้เขียนไฟล์คอนฟิกนั้นแค่ทีเดียวแล้วไปแก้ไฟล์คอนฟิกอื่นๆที่ include เข้าไปแทน

หลังจากการค้นหาอยู่นานผมก็ค้นพบวิธีการที่ทำให้มันไม่ต้องยุ่งกับ /etc/resolv.conf ได้ด้วยการ
...
...
เลิกเขียนโปรแกรมซะ

โว้ย ทำไมมันไม่มีวิธีวะ หาแทบพลิกแผ่นดินแล้ว สุดท้ายโปรแกรมของผมก็จำต้องไปแก้ไขไฟล์ /etc/resolv.conf ไปก่อนเพราะงานมันเร่งต้องส่งลูกค้าแล้ว

แล้วช่วงนี้ต้องกลับมาแก้ไขโครงสร้างของระบบใหม่ คราวนี้ได้รับคำสั่งมาว่า /etc ต้องโดน mount เป็น read-only ก็เลยต้องกลับมาค้นดูอีกทีว่าจะทำไงดี หลังจากถามพี่ที่บริษัทก็พบว่าตัว resolver ของ FreeBSD นั้นมันใส่ชื่อไฟล์ลงไปในโค้ดเลย โอ้ว แม่เจ้า ทำงี้ได้ไงฟระ

วิธีแก้
หลังจากที่ไล่โค้ดดู (อยู่ใน /usr/include/resolv.h) ก็เห็นส่วนที่ไว้ระบุไฟล์คอนฟิก มันระบุโดยการใช้ define เอาครับ ดังนั้นเราสามารถ define ค่าของตัวแปรใหม่ได้ตอนสั่งคอมไพล์ ค่อยยังชั่วหน่อย ไม่ต้องแก้โค้ด แต่ว่าเราก็ไม่สามารถเปลี่ยน path ของไฟล์คอนฟิกแบบ dynamic ได้อยู่ดี (โลกนี้มันช่างโหดร้ายจริงๆ)

ตัวแปรที่ไว้กำหนด path ของไฟล์คอนฟิกของ resolver นั้นชื่อว่า

_PATH_RESCONF

ขั้นตอนต่อไป เดี๋ยวจะลองคอมไพล์โดย define ตัวแปรนี้ชี้ไปที่อื่นดู
ตัวผมเองก็ไม่เคยคอมไพล์เคอเนลโดยใส่ออปชันอะไรแบบนี้มาก่อนเหมือนกัน ยังไม่ค่อยแน่ใจว่าต้องใส่ยังไง เดี๋ยวลองเสร็จแล้วจะมาสรุปอีกที

Tuesday, June 22, 2010

ขำ ^ 2

joke[0]

Several scientists were all posed the following question: "What is 2 * 2 ?"

The engineer whips out his slide rule (so it's old) and shuffles it back and forth, and finally announces "3.99".

The physicist consults his technical references, sets up the problem on his computer, and announces "it lies between 3.98 and 4.02".

The mathematician cogitates for a while, then announces: "I don't know what the answer is, but I can tell you, an answer exists!".

Philosopher smiles: "But what do you mean by 2 * 2 ?"

Logician replies: "Please define 2 * 2 more precisely."

The sociologist: "I don't know, but is was nice talking about it".

Behavioral Ecologist: "A polygamous mating system".

Medical Student : "4"

All others looking astonished : "How did you know ??"

Medical Student : :I memorized it."



joke[1]

Biologists think they are biochemists,

Biochemists think they are Physical Chemists,

Physical Chemists think they are Physicists,

Physicists think they are Gods,

And God thinks he is a Mathematician...

Wednesday, April 14, 2010

GNOME บน FreeBSD 8.0

อีกหนึ่งโปรเจกต์ FreeBSD ของผมคือการเอา FreeBSD มาใช้เป็นเดสก์ท็อปครับ (ฮ่าๆๆๆ เท่มั้ยหละ) แน่นอนว่าจะเอามาใช้เป็นเดสก์ท็อปก็ต้องมีการติดตั้ง Desktop Environment ไม่งั้นจะใช้ไงหละ

DE ที่ผมเลือกแบบไม่ต้องคิดเลยก็คือ GNOME ครับ (เห็นบางคนอ่านมันว่า "กะโนม" (คล้ายๆแบบกะนู) แต่ผมอ่านมันว่าจีโนม) ขี้เกียจหาอันใหม่ เอาอันนี้แหละ คุ้นเคยกันดีเพราะผมเคยลองใช้บน FreeBSD 7.x มาก่อนแล้วรอบนึงครับ ก็เลยคิดว่าบน 8.0 ก็คงเหมือนๆเดิม ก็ลงตามเสต็ปเดิม ปรากฏว่าตอนสั่ง GNOME ทำงานมันดันฟ้องว่าไม่มีไฟล์ /var/run/dbus.pid

หลังจากโง่อยู่นานก็พบว่า GNOME บน 8.0 มันต้องการเซอวิส dbus ด้วย (ไอ้ error ที่มันฟ้องแปลว่ามันหาไฟล์ process id dbus ไม่เจอ นั่นเป็นเพราะว่า dbus มันไม่ได้รันอยู่) เพราะงั้นเราต้องสตาร์ทมันก่อนสตาร์ท GNOME

หลังจากที่รัน GNOME ขึ้นมาได้ก็พบปัญหาอีกอย่างนึงคือ touchpad มันไม่ทำงานครับ ผมไม่สามารถควบคุมเคอเซอร์ได้ ตอนแรกก็นึกว่าเป็นปัญหาที่ FreeBSD กับ touchpad ของผม แต่บน X ธรรมดามันดันทำงานได้แฮะ อืม แล้วเป็นเพราะอะไรหละเนี่ย

พอค้นไปค้นมาก็เจอว่า GNOME เนี่ยมันต้องการเซอวิส hald รันด้วย ดังนั้นเราก็ต้องไปสตาร์ทมันก่อนอีกเหมือนกัน
หลังจากที่สตาร์ทเซอวิส 2 ตัวนี้แล้ว GNOME ก็จะใช้งานได้ตามปกติ

ปล[0] การสตาร์ท dbus กับ hald สามารถสตาร์ทได้ด้วย rc script ใน /usr/local/etc/rc.d ชื่อสคิปท์คือ dbus และ hald (ถ้าตอนลงไม่ได้คอนฟิกอะไรเป็นพิเศษมันจะอยู่ที่พาธนี้แหละ)
ปล[1] ปกติผมสั่ง `gdm` จากคอมมานด์ไลน์เลย แต่วันนี้พึ่งนึกได้ มันต้องมี rc script สิ พอลองค้นดูก็เห็นอยู่ที่ /usr/local/etc/rc.d/gdm

Monday, April 12, 2010

[C code] string copy ใน C

ความสุขอย่างนึงในการเขียนโปรแกรมของผมคือการแก้โค้ดที่ทำงานได้ให้มันสั้นลงครับ (แล้วโค้ดที่ทำงานได้มันจะบั๊กก็ตอนแก้ให้สั้นเนี่ยแหละ ฮ่าๆๆ) ไม่รู้สิ รู้สึกว่่ามันเจ๋งดีนะเวลาได้เขียนโค้ด while หรือ for ปล่าวๆแบบให้การทำงานอยู่ในเงื่อนไขของลูปไปเลย เหอๆ
เมื่อวานผมก็อ่านโค้ด string copy ในหนังสือภาษาซีเล่มนึง โค้ดนี้เขียนโดยใช้ใช้พอยท์เตอร์ (เพราะมันอยู่ในบทเรื่องพอยท์เตอร์) โค้ดในหนังสือตอนแรกออกมาเป็นแบบนี้ครับ

void strcpy(char *s, char *t) {
while((*s = *t) != '\0') {
s++;
t++;
}
}

ไอ้คนอย่างผมก็เลยนั่งเขียนให้มันเหลือแค่บรรทัดเดียวไอ้ตรงวน while โค้ดผมได้ออกมาแบบนี้ครับ

void strcpy(char *s, char *t) {
while((*s++ = *t++) != '\0');
}

แฮ่ ในที่สุดมันก็เหลือบรรทัดเดียว ซึ่งพอผมอ่านหนังสือต่อไปมันก็ลดรูปมาเหลือเท่าที่ผมเขียนครับ
แต่ยังไม่หมด ตัวอย่างต่อมามันดันเขียนลูปได้สั้นกว่านี้อีก!!!

void strcpy(char *s, char *t) {
while(*s++ = *t++);
}

โห มันใช้ความบังเอิญที่ว่า character constant '\0' ดันมีค่าเป็น 0 พอดีมาเป็นเงื่อนไขในการเช็ค
สุดยอดไปเลยหวะ ชอบๆ

ก็เลยต้องมาเขียนบล็อกเก็บไว้หน่อย :)

Friday, April 9, 2010

[C code] if in C

ไปอ่านเจอมาจาก stackoverflow (แต่จำกระทู้ไม่ได้เลยไม่ได้ทำลิงค์ไป) เห็นมีคนมาถามว่าเวลาเขียน if เปรียบเทียบตัวแปรกับตัวเลข เขียนแบบนี้มันดีกว่ายังไง

if(4 == i)

งงดิครับ ตั้งแต่เกิดมาไม่เคยเห็นครูบาอาจารย์ที่ไหนบอกว่าเขียนแบบนี้มันดีกว่า ไอ้คนตั้งกระทู้มันก็ไม่รู้ไปได้ยินมาจากไหน แต่ก็มีคนเข้ามาตอบให้ได้ว่าดีกว่ายังไง
โค้ดแบบนี้จะดีกว่าเฉพาะในภาษาซีเท่านั้นครับ เพราะว่าเป็นการลดบั๊กจากการพิมพ์ผิด เพราะว่าในภาษาซีถ้าเราตั้งใจจะเปรียบเทียบค่าโดยพิมพ์แบบนี้

if(i == 4)

เป็น

if(i = 4)

จะได้ว่า if นี้เป็นจริงเสมอ (ส่วนจาวาจะคอมไพล์ไม่ผ่าน) ดังนั้นพอเขียนกลับกัน ถึงเขียนผิดเป็น

if(4 = i)

คอมไพเลอร์ก็จะฟ้องขึ้นมา
แหม่ ไอ้คนคิดวิธีเขียนโค้ดแบบนี้มันสุดยอดจริงๆ