--- 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)
--- 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
--- 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) :
"""