-*- indented-text -*- In the future, we'll want to allow the IO routines to return EWOULDBLOCK and then have us return all the way to the caller. This will allow us to integrate into select-based servers such as Squid. This isn't done yet, but we want to move towards it. This is particularly interesting to encoding, since it's more complicated. It implies: * No state stored on the stack during IO calls -- everything must be in structures where we can leave it and come back. * A way for IO routines to return ``I'd block'' * The IO wrapper (i.e. mapptr) musn't discard data that's been read from the network until we know it's no longer needed. Here are some interesting parts of the GNU libc manual: ---------------------------------------------------------------------- - Macro: int EAGAIN Resource temporarily unavailable; the call might work if you try again later. The macro `EWOULDBLOCK' is another name for `EAGAIN'; they are always the same in the GNU C library. This error can happen in a few different situations: * An operation that would block was attempted on an object that has non-blocking mode selected. Trying the same operation again will block until some external condition makes it possible to read, write, or connect (whatever the operation). You can use `select' to find out when the operation will be possible; *note Waiting for I/O::. *Portability Note:* In many older Unix systems, this condition was indicated by `EWOULDBLOCK', which was a distinct error code different from `EAGAIN'. To make your program portable, you should check for both codes and treat them the same. * A temporary resource shortage made an operation impossible. `fork' can return this error. It indicates that the shortage is expected to pass, so your program can try the call again later and it may succeed. It is probably a good idea to delay for a few seconds before trying it again, to allow time for other processes to release scarce resources. Such shortages are usually fairly serious and affect the whole system, so usually an interactive program should report the error to the user and return to its command loop. - Macro: int EWOULDBLOCK In the GNU C library, this is another name for `EAGAIN' (above). The values are always the same, on every operating system. C libraries in many older Unix systems have `EWOULDBLOCK' as a separate error code. [....] - Function: ssize_t read (int FILEDES, void *BUFFER, size_t SIZE) The `read' function reads up to SIZE bytes from the file with descriptor FILEDES, storing the results in the BUFFER. (This is not necessarily a character string and there is no terminating null character added.) The return value is the number of bytes actually read. This might be less than SIZE; for example, if there aren't that many bytes left in the file or if there aren't that many bytes immediately available. The exact behavior depends on what kind of file it is. Note that reading less than SIZE bytes is not an error. A value of zero indicates end-of-file (except if the value of the SIZE argument is also zero). This is not considered an error. If you keep calling `read' while at end-of-file, it will keep returning zero and doing nothing else. If `read' returns at least one character, there is no way you can tell whether end-of-file was reached. But if you did reach the end, the next read will return zero. In case of an error, `read' returns -1. The following `errno' error conditions are defined for this function: `EAGAIN' Normally, when no input is immediately available, `read' waits for some input. But if the `O_NONBLOCK' flag is set for the file (*note File Status Flags::), `read' returns immediately without reading any data, and reports this error. *Compatibility Note:* Most versions of BSD Unix use a different error code for this: `EWOULDBLOCK'. In the GNU library, `EWOULDBLOCK' is an alias for `EAGAIN', so it doesn't matter which name you use. [....] - Function: ssize_t write (int FILEDES, const void *BUFFER, size_t SIZE) The `write' function writes up to SIZE bytes from BUFFER to the file with descriptor FILEDES. The data in BUFFER is not necessarily a character string and a null character is output like any other character. The return value is the number of bytes actually written. This may be SIZE, but can always be smaller. Your program should always call `write' in a loop, iterating until all the data is written. Once `write' returns, the data is enqueued to be written and can be read back right away, but it is not necessarily written out to permanent storage immediately. You can use `fsync' when you need to be sure your data has been permanently stored before continuing. (It is more efficient for the system to batch up consecutive writes and do them all at once when convenient. Normally they will always be written to disk within a minute or less.) Modern systems provide another function `fdatasync' which guarantees integrity only for the file data and is therefore faster. You can use the `O_FSYNC' open mode to make `write' always store the data to disk before returning; *note Operating Modes::. In the case of an error, `write' returns -1. The following `errno' error conditions are defined for this function: `EAGAIN' Normally, `write' blocks until the write operation is complete. But if the `O_NONBLOCK' flag is set for the file (*note Control Operations::), it returns immediately without writing any data, and reports this error. An example of a situation that might cause the process to block on output is writing to a terminal device that supports flow control, where output has been suspended by receipt of a STOP character. *Compatibility Note:* Most versions of BSD Unix use a different error code for this: `EWOULDBLOCK'. In the GNU library, `EWOULDBLOCK' is an alias for `EAGAIN', so it doesn't matter which name you use. On some systems, writing a large amount of data from a character special file can also fail with `EAGAIN' if the kernel cannot find enough physical memory to lock down the user's pages. This is limited to devices that transfer with direct memory access into the user's memory, which means it does not include terminals, since they always use separate buffers inside the kernel. This problem does not arise in the GNU system. ---------------------------------------------------------------------- Therefore we should also run all of the mapptr test cases with O_NONBLOCK. We ought to handle EINTR as well!