# HG changeset patch # User Tero Marttila # Date 1250461468 -10800 # Node ID e6b670dbfe3b140a047e5b81be27a2fae623924e # Parent 43a57943af9fa93c30b7bbd5079cbdee469b53d1 socket.setblocking diff -r 43a57943af9f -r e6b670dbfe3b qmsk/net/libc.pxd --- a/qmsk/net/libc.pxd Mon Aug 17 01:03:40 2009 +0300 +++ b/qmsk/net/libc.pxd Mon Aug 17 01:24:28 2009 +0300 @@ -41,6 +41,19 @@ int close (int fd) +cdef extern from "fcntl.h" : + int fcntl (int fd, int cmd, ...) + + enum : + F_GETFL + F_SETFL + + enum : + O_NONBLOCK + +# set a specific flag(s) to the given value +cdef fcntl_set_flag (int fd, int flag, bint value) + cdef extern from "alloca.h" : # XXX: this is unsafe because there is it may fail nastily for allocations that won't fit on the stack - SIGSEGV void* alloca (size_t size) diff -r 43a57943af9f -r e6b670dbfe3b qmsk/net/libc.pyx --- a/qmsk/net/libc.pyx Mon Aug 17 01:03:40 2009 +0300 +++ b/qmsk/net/libc.pyx Mon Aug 17 01:24:28 2009 +0300 @@ -1,6 +1,28 @@ from qmsk.net.libc cimport * from qmsk.net.py cimport raise_errno +cdef fcntl_set_flag (int fd, int flag, bint value) : + """ + Set the given FCNTL file status flag(s) to the given boolean value. + + This will first get the current flags, then compute the new flags, and then update them if they have changed. + """ + + # get current flags + cdef int old_flags = fcntl(fd, F_GETFL, 0) + + if old_flags < 0 : + raise_errno('fcntl') + + # set bit + cdef int new_flags = (old_flags & ~flag) | (flag if value else 0) + + if new_flags != old_flags : + # set flags + if fcntl(fd, F_SETFL, new_flags) : + raise_errno('fcntl') + + #cdef class Errno (py.OSError) : # def __init__ (self, func) : # self.func = func diff -r 43a57943af9f -r e6b670dbfe3b qmsk/net/socket/socket.pyx --- a/qmsk/net/socket/socket.pyx Mon Aug 17 01:03:40 2009 +0300 +++ b/qmsk/net/socket/socket.pyx Mon Aug 17 01:24:28 2009 +0300 @@ -111,6 +111,16 @@ """ return self.fd + + def setblocking (self, bint blocking = True) : + """ + Control the OS-level nonblocking-IO mode flag for this socket. + + blocking - True for normal blocking operation, False to use non-blocking operation + """ + + # fcntl magic + libc.fcntl_set_flag(self.fd, libc.O_NONBLOCK, not blocking) def bind (self, sockaddr addr) : """