nonblocking_io_in_nspr.rst (5987B)
1 Nonblocking IO in NSPR 2 ====================== 3 4 5 Introduction 6 ------------ 7 8 Previously, all I/O in the NetScape Portable Runtime (NSPR) was 9 *blocking* (or *synchronous*). A thread invoking an io function is 10 blocked until the io operation is finished. The blocking io model 11 encourages the use of multiple threads as a programming model. A thread 12 is typically created to attend to one of the simultaneous I/O operations 13 that may potentially block. 14 15 In the *nonblocking* io model, a file descriptor may be marked as 16 nonblocking. An io function on a nonblocking file descriptor either 17 succeeds immediately or fails immediately with 18 <tt>PR_WOULD_BLOCK_ERROR</tt>. A single thread is sufficient to attend 19 to multiple nonblocking file descriptors simultaneously. Typically, this 20 central thread invokes <tt>PR_Poll()</tt> on a set of nonblocking file 21 descriptors. (Note: <tt>PR_Poll()</tt> also works with blocking file 22 descriptors, although it is less useful in the blocking io model.) When 23 <tt>PR_Poll()</tt> reports that a file descriptor is ready for some io 24 operation, the central thread invokes that io function on the file 25 descriptor. 26 27 .. _Creating_a_Nonblocking_Socket: 28 29 Creating a Nonblocking Socket 30 ----------------------------- 31 32 *Only sockets can be made nonblocking*. Regular files always operate in 33 blocking mode. This is not a serious constraint as one can assume that 34 disk I/O never blocks. Fundamentally, this constraint is due to the fact 35 that nonblocking I/O and <tt>select()</tt> are only available to sockets 36 on some platforms (e.g., Winsock). 37 38 In NSPR, a new socket returned by <tt>PR_NewTCPSocket()</tt> or 39 <tt>PR_NewUDPSocket()</tt> is always created in blocking mode. One can 40 make the new socket nonblocking by using <tt>PR_SetSockOpt()</tt> as in 41 the example below (error checking is omitted for clarity): 42 43 | 44 | <tt>PRFileDesc \*sock;</tt> 45 | **<tt>PRIntn optval = 1;</tt>** 46 47 <tt>sock = PR_NewTCPSocket();</tt> 48 49 :: 50 51 /* 52 * Make the socket nonblocking 53 */ 54 55 PR_SetSockOpt(sock, PR_SockOpt_Nonblocking, &optval, sizeof(optval)); 56 57 .. _Programming_Constraints: 58 59 Programming Constraints 60 ----------------------- 61 62 There are some constraints due to the use of NT asynchronous I/O in the 63 NSPR. In NSPR, blocking sockets on NT are associated with an I/O 64 completion port. Once associated with an I/O completion port, we can't 65 disassociate the socket from the I/O completion port. I have seen some 66 strange problems with using a nonblocking socket associated with an I/O 67 completion port. So the first constraint is: 68 69 **The blocking/nonblocking io mode of a new socket is committed the 70 first time a potentially-blocking io function is invoked on the 71 socket. Once the io mode of a socket is committed, it cannot be 72 changed.** 73 74 The potentially-blocking io functions include <tt>PR_Connect()</tt>, 75 <tt>PR_Accept()</tt>, <tt>PR_AcceptRead()</tt>, <tt>PR_Read()</tt>, 76 <tt>PR_Write()</tt>, <tt>PR_Writev()</tt>, <tt>PR_Recv()</tt>, 77 <tt>PR_Send()</tt>, <tt>PR_RecvFrom()</tt>, <tt>PR_SendTo()</tt>, and 78 <tt>PR_TransmitFile(),</tt> and do not include <tt>PR_Bind()</tt> and 79 <tt>PR_Listen()</tt>. 80 81 In blocking mode, any of these potentially-blocking functions requires 82 the use of the NT I/O completion port. So at that point we must 83 determine whether to associate the socket with the I/O completion or 84 not, and that decision cannot be changed later. 85 86 There is a second constraint, due to the use of NT asynchronous I/O and 87 the recycling of used sockets: 88 89 **The new socket returned by <tt>PR_Accept()</tt> or 90 <tt>PR_AcceptRead()</tt> inherits the blocking/nonblocking io mode of 91 the listening socket and this cannot be changed.** 92 93 The socket returned by <tt>PR_Accept()</tt> or <tt>PR_AcceptRead()</tt> 94 on a blocking, listening socket may be a recycled socket previously used 95 in a <tt>PR_TransmitFile()</tt> call. Since <tt>PR_TransmitFile()</tt> 96 only operates in blocking mode, this recycled socket can only be reused 97 in blocking mode, hence the above constraint. 98 99 Because these constraints only apply to NT, it is advised that you test 100 your cross-platform code that uses nonblocking io on NT early in the 101 development cycle. These constraints are enforced in the debug NSPR 102 library by assertions. 103 104 .. _Differences_from_Blocking_IO: 105 106 Differences from Blocking IO 107 ---------------------------- 108 109 - In nonblocking mode, the timeout argument for the io functions is 110 ignored. 111 - <tt>PR_AcceptRead()</tt> and <tt>PR_TransmitFile()</tt> only work on 112 blocking sockets. They do not make sense in nonblocking mode. 113 - <tt>PR_Write()</tt>, <tt>PR_Send()</tt>, <tt>PR_Writev()</tt> in 114 blocking mode block until the entire buffer is sent. In nonblocking 115 mode, they cannot block, so they may return with just sending part of 116 the buffer. 117 118 .. _PR_Poll()_or_PR_Select(): 119 120 PR_Poll() or PR_Select()? 121 ------------------------- 122 123 <tt>PR_Select()</tt> is deprecated, now declared in 124 <tt>private/pprio.h</tt>. Use <tt>PR_Poll()</tt> instead. 125 126 The current implementation of <tt>PR_Select()</tt> simply calls 127 <tt>PR_Poll()</tt>, so it is sure to have worse performance. Also, 128 native file descriptors (socket handles) cannot be added to 129 <tt>PR_fd_set</tt>, i.e., the functions <tt>PR_FD_NSET</tt>, 130 <tt>PR_FD_NCLR</tt>, <tt>PR_FD_NISSET</tt> do not work. 131 132 PR_Available() 133 -------------- 134 135 When <tt>PR_Available()</tt> returns 0, it may mean one of two things: 136 137 - There is no data available for reading on that socket. I.e., 138 <tt>PR_Recv()</tt> would block (a blocking socket) or fail with 139 <tt>PR_WOULD_BLOCK_ERROR</tt> (a nonblocking socket). 140 - The TCP connection on that socket has been closed (end of stream). 141 142 These two cases can be distinguished by <tt>PR_Poll()</tt>. If 143 <tt>PR_Poll()</tt> reports that the socket is readable (i.e., 144 <tt>PR_POLL_READ</tt> is set in <tt>out_flags</tt>), and 145 <tt>PR_Available()</tt> returns 0, this means that the socket connection 146 is closed. 147 148 .. _Current_Status: 149 150 Current Status 151 -------------- 152 153 Implemented across all supported platforms.