Friday, May 30, 2008

My Pyhton 's process was Killed

ช่วงนี้กำลังทดสอบโปรแกรมที่เขียนด้วย python บนเครื่อง Production ที่ใช้ AIX เป็น OS
หลังจาก run program ไปได้พักหนึ่ง, โปรแกรมก็หยุดทำงานพร้อมกับมีข้อความแบบนี้ต่อท้าย

killed

คำถามแรกก็คือ "ใคร kill กูวะ"
process ของน้องชิ้ม (น้องที่ทำงาน) ตกเป็นผู้ต้องสงสัยรายแรก
(น้องชิ้มเขียน script ที่คอย monitor ว่ามี process ไหนใช้ cpu ผิดปกติบ้าง
ถ้าเจอก็จะจัดการ kill เสีย)
หลังจากน้องชิ้มตรวจดู log file สักพัก ก็บอกว่า "script ผมไม่ได้ทำครับพี่"

ผู้ต้องสงสัยรายถัดไป ก็คือ message ข้างล่างนี้

sem_trywait: Permission denied
sem_wait: Permission denied
sem_post: Permission denied

message นี้เกิดขึ้นในระหว่างทำงาน

หลังจากค้น google ก็พบว่า kernel น่าจะเป็นคนสั่ง kill process เอง (http://tinyurl.com/59e7yw)
ส่วนสำเหตุก็คือ bug ตัวนี้ http://bugs.python.org/issue1234
นัยว่าเจ้า python มันคงเรียกใช้ sem_wait มากเกินไป จน kernel มันทนไม่ได้

ว่าแล้วก็รอแปะ patch และ compile python เย็นนี้
จันทร์หน้ามารอดูผลกันใหม่

Related link from Roti

เปิดเน็ต เปิดใจ

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


ปกป้องเสรีภาพของเรา
บนอินเทอร์เน็ตของเรา
ร่วมลงชื่อในแถลงการณ์

Related link from Roti

Tuesday, May 27, 2008

Pyro

ช่วงนี้มีความจำเป็นต้องใช้ remote call บน python, ค้น google ดูก็พบเจ้า Pyro
หลังจากอ่านหลักการแล้วก็อ๋อ เพราะทำงานแนวเดิียวกับ java RMI

หลักการทำงาน
  • Name Server
    เพื่อให้ client สามารถ lookup service ได้ง่ายๆ, Pyro ก็เลย provide Name Server มาให้ด้วย
    เจ้า name server ที่ pyro ให้มา มันแบ่งออกเป็น 2 ประเภทคือ
    • Regular, non-persistent
      ตัวนี้พอ name server process ตาย, ค่าต่างๆใน registry ก็หายไปด้วย
    • Persistent
      ค่าต่างๆใน registry จะเก็บไว้บน disk

    เพื่อเพิ่ม availability, เจ้าตัว name server นี้ ยังสามารถ start ในแบบ Paired mode ได้อีกด้วย โดยทั้งคู่จะทำ replicate registry ซึ่งกันและกันไว้

  • Client
    การที่ client จะติดต่อ server ได้นั้น ขั้นแรกก็ต้องหา Name Server ให้เจอเสียก่อน
    วิธีการหา Name Server ก็คือ
    locator = Pyro.naming.NameServerLocator()
    ns = locator.getNS()

    ขั้นตอนการทำงานภายในก็คือ มันจะทำการ broadcast message ออกไป
    เจ้า Name server (ซึ่ง implement broadcast listener) ก็จะตอบกลับมา

    Note: กรณีของผม ผมลองใช้ boardcast บน production server แล้ว, message มันหายต๋อมไป (ด้วยความขี้เกียจไปไล่หาสาเหตุ)
    ผมก็เลย config ให้ NameServerLocator มันต่อตรงไปที่ Name Server โดยตรงเลย แทนที่จะ broadcast
    การ config ให้ต่อตรงทำได้โดย
    Pyro.config.PYRO_NS_HOSTNAME='YOUR_HOSTNAME'

    หลังจากหา Name Server เจอแล้ว ขั้นถัดไปก็คือ ทำการถามหา URI ของ server ที่ต้องการ
    uri = ns.resolve('my_service')

    เมื่อได้ uri แล้ว สุดท้ายก็คือทำการสร้าง proxy object ซึ่งเจ้า Pyro แบ่งประเภท Proxy ออกเป็น 2 แบบคือ
    • Proxy ธรรมดา
    • Proxy ที่สามารถ access attribute ของ remote object ได้ด้วย

    วิธีการสร้าง proxy ก็คือ
    obj = uri.getProxy()
    # or
    obj = uri.getAttrProxy()

    ที่เหลือ ก็เป็นการเรียกใช้ method ต่างๆบน remote object ที่เราได้มา

  • Server
    การทำงานฝั่ง server เริ่มต้นด้วยการสร้าง daemon object
    (มี parameter เป็น name server object ซึ่ง lookup มาด้วยวิธีเดียวกันกับ client)
    daemon = Pyro.core.Daemon()
    daemon.useNameServer(ns)

    ข้อควรระวังก็คือ ต้องระวังเรื่อง reference ถึง object daemon ของเรา
    มิเช่นนั้น garbage collection อาจกวาด daemon เราทิ้งไปได้

    หลังจากได้ daemon มา ก็ทำการสร้าง Object instance ที่ต้องการให้ client ต่อใช้
    เนื่องจาก pyro ต้องหลอก object ของเราว่ามันทำงานเหมือนกับอยู่ในสภาพแวดล้อมแบบ stand-alone
    ดังนั้น Remote Object ของเราก็เลยต้องถูกห่อไว้ใน Pyro.core.ObjBase
    ซึ่งเราสามารถทำได้ 3 วิธีคือ
    • ให้ Remote class ของเรา extend Pyro.core.ObjBase ตรงๆเลย
    • delegate pattern
      บางครั้งเราอยากเขียน Remote Class โดยไม่อยากให้มี dependency ถึง Pyro เลย
      obj = Pyro.core.ObjBase()
      myservice = MyService()
      obj.delegateTo(myservice)

    • สร้าง class ใหม่ที่ extend ทั้ง Pyro.core.ObjBase และ Service class ของเรา
      class ServiceImpl(Pyro.core.ObjBase, MyService):
      def __init__(self):
      Pyro.core.ObjBase.__init__(self)
      MyService.__init__(self)

      ขั้นถัดไปก็คือทำการ binding
      โดยสั่ง connect daemon กับ​ Object instance
      ซึ่งเจ้า daemon จะจัดการไปคุยกับ Name Server ให้เราเอง
      daemon.connect(obj, 'my_service')


      สุดท้ายก็คือการสั่งให้ daemon วน loop รับ request จาก client
      daemon.requestLoop()




สิ่งที่ต้องระวังในการ implement remote object ของเราก็คือ
มันต้องเป็น thread safe เนื่องจาก daemon จะใช้วิธีแตก thread เมื่อมี incoming connection วิ่งเข้ามา
feature ที่น่าสนใจในประเด็นนี้ ก็คือ TLS (Thread Local Storage)
ซึ่งช่วยให้เราเก็บข้อมูลโดยการ bind local data เข้ากับ thread แทน

feature ที่น่าสนใจอีกอย่างก็คือ Mobile code
case นี้เป็นกรณีที่ client call ไปยัง remote object โดยส่ง argument เป็น object ที่ไม่มี code อยู่บน server มาด้วย
ซึ่งโดยปกติ มันจะเกิด error ประเภท NoModuleError
แต่ถ้าเรากำหนด configuration ให้ Pyro ใช้ feature Mobile code
เวลาที่ server เจอ code ที่ไม่รู้จัก มันก็จะ request code มายัง client
กรณี mobile code นี้ support 2-way
นั่นคือ support กรณี server return object ที่ไม่มี code บน client ด้วย

Related link from Roti

Sunday, May 25, 2008

ป้ายแดง

ช่วงนี้โรงเรียนลูกเปิดเทอมแล้ว
ผมก็เลยถอยรถคันใหม่ออกมาส่งลูกโดยเฉพาะ
เลือกรุ่น entry level (ราคาถูกกว่าคันของ ipats) พร้อมด้วยเบาะนั่งของเด็ก
ขี่ไปส่งลูกแล้วรู้สึกมั่นใจในความปลอดภัยขึ้นเยอะ



ส่วนคันเก่าก็ไม่ได้ทิ้งไปไหน พอส่งลูกเสร็จก็เปลี่ยนเป็นขี่เสือหมอบไปทำงาน
เพราะเจ้าเสือหมอบมันเร่งแซงได้ทันใจกว่ากันเยอะ

Related link from Roti