Friday, February 18, 2011

Problem in swap code

Our only one blog fan, m3rlinez, told me that the one line swap code that I wrote in the previos entry cannot use when two variables are the same allocation such as

a[i] ^= a[j] ^= a[i] ^= a[j]; // when i = j

Thanks him to pointed this issue.

Wednesday, February 16, 2011

double fork magic

เริ่มที่ zombie process

zombie process คืออะไร
zombie process คือ process ที่ทำงานจบแล้วแต่ตัวมันยังอยู่ใน process table ของ OS เพื่อรอให้ parent process มาอ่านค่า exit status ของมัน แต่ก็ไม่มาอ่านซักที

แล้วเมื่อไหร่ parent process จะมาอ่าน exit status
เป็นไปได้สองทาง
  1. ในโค้ดเรียก function wait ( pid_t wait(int *stat_loc) ) แล้วโปรแกรมจะหยุดรอจนกว่า process ลูกจะทำงานเสร็จ
  2. เขียน signal handling ให้จัดการ SIGCHLD (SIGCHLD เป็น signal ที่ส่งมาบอกว่า process ลูกทำงานเสร็จแล้ว ให้ parent process ไปจัดการต่อด้วย)

double fork คืออะไร
double fork เป็นรูปแบบการเขียนโค้ดแบบหนึ่งที่ไว้ป้องกันการเกิด zombie process การเขียนโค้ดแบบ double fork นี้ใช้ประโยชน์จากการที่เมื่อ parent process จบการทำงานในขณะที่ child process ยังทำงานไม่เสร็จ โดย child process นั้นจะกลายเป็น process ลูกของ init process แทน ซึ่งจะคอยกำจัด child process พวกนี้ภายหลัง (init process คืออะไรอะเหรอ โอ๊ย เรื่องมันยาว)

แล้วตกลงมันทำงานยังไงหละว้อย
ยกตัวอย่างเปรียบเทียบให้เห็นภาพเลยละกัน
  1. ตัวอย่างแรกของการเกิด zombie สมมติว่ามี process A fork ลูกออกมาเป็น process B และเมื่อ B ทำงานเสร็จ A ไม่มาจัดการ SIGCHLD ที่ส่งมาทำให้ B กลายเป็น zombie
  2. ตัวอย่างการทำ double fork แทนที่ process A จะ fork B ออกมาเลย เราเขียนโค้ดให้ A fork process X ออกมาก่อน โดยหน้าที่อย่างเดียวของ X คือ fork B เมื่อ fork B เสร็จก็ให้ X จบการทำงาน ซึ่งเมื่อมาถึงขั้นนี้ B จะกลายเป็น orphan process และจะกลายเป็น process ลูกของ init เมื่อ B ทำงานเสร็จ init ก็จะมาจัดการเคลียร์ B ออกจาก process table ให้
ทีนี้ก็จะไม่มี zombie process อีกต่อไป

Friday, February 11, 2011

Swap two variable values code in one line.

First code pattern that comes to my mind when I want to swap two variable value is

int c;
c = a;
a = b;
b = c;

I found this code in every novice programming book, also in my programming class.
But I've heard one challenging problem (for me as a novice) that try to swap without temporary variable (that is c, in my code.) The code uses knowledge technique from logic class.

a = a ^ b;
b = a ^ b;
a = a ^ b;

The caret symbol (^) represents bitwise xor.
Recently, I found the code that written it in one line for making it more cool and less understanding that is

a ^= b ^= a ^= b;

Impressed!

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...