socket.setblocking
authorTero Marttila <terom@fixme.fi>
Mon, 17 Aug 2009 01:24:28 +0300
changeset 19 e6b670dbfe3b
parent 18 43a57943af9f
child 20 0e4933d5862e
socket.setblocking
qmsk/net/libc.pxd
qmsk/net/libc.pyx
qmsk/net/socket/socket.pyx
--- 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) :
         """