Browse Source

add some man pages

master
Felix von Leitner 18 years ago
parent
commit
5617c437b8
  1. 1
      CHANGES
  2. 28
      io/io_canread.3
  3. 29
      io/io_canwrite.3
  4. 11
      io/io_check.3
  5. 24
      io/io_close.3
  6. 14
      io/io_closeonexec.3
  7. 17
      io/io_createfile.3
  8. 18
      io/io_dontwantread.3
  9. 18
      io/io_dontwantwrite.3
  10. 20
      io/io_eagain.3
  11. 19
      io/io_fd.3
  12. 14
      io/io_finishandshutdown.3
  13. 23
      io/io_getcookie.3
  14. 43
      io/io_nonblock.3
  15. 19
      io/io_passfd.3
  16. 28
      io/io_pipe.3
  17. 15
      io/io_readfile.3
  18. 18
      io/io_receivefd.3
  19. 20
      io/io_sendfile.3
  20. 8
      io/io_sendfile.c
  21. 25
      io/io_setcookie.3
  22. 18
      io/io_socketpair.3
  23. 18
      io/io_timeout.3
  24. 17
      io/io_timeouted.3
  25. 42
      io/io_tryread.3
  26. 23
      io/io_tryreadtimeout.3
  27. 51
      io/io_trywrite.3
  28. 1
      io/io_trywrite.c
  29. 23
      io/io_trywritetimeout.3
  30. 1
      io/io_waitwrite.c
  31. 21
      io/io_wantread.3
  32. 21
      io/io_wantwrite.3
  33. 2
      io_internal.h

1
CHANGES

@ -1,6 +1,7 @@
0.19:
add io_socketpair
add io_passfd and io_receivefd (and test/fdpassing.c)
io_trywrite and io_waitwrite not ignore SIGPIPE
0.18:
make libowfat compile on BSD again (sorry, and thanks to everyone who

28
io/io_canread.3

@ -0,0 +1,28 @@
.TH io_canread 3
.SH NAME
io_canread \- return a file descriptor that can be read from
.SH SYNTAX
.B #include <io.h>
int64 \fBio_canread\fP();
.SH DESCRIPTION
io_canread returns the next file descriptor that can be read from.
You have to have used io_wantread() on the file descriptor earlier, and
you have to have called io_wait() or io_waituntil().
These functions then keep an internal data structure on which
descriptors were reported readable by the operating system.
Please note that there is no guarantee that there still is data that can
be read from the descriptor, just that there was data when io_wait() or
io_waituntil() were called. Another process could have read the data
before you. Look at the result from io_tryread().
If there are no more descriptors that you can write to without blocking,
io_canwrite will return -1. In this case you should call io_wait() or
io_waituntil() again.
You should use io_tryread(3) to read from the descriptor, not plain
read(2). If you use read(2) and you get EAGAIN, call io_eagain(3).
.SH "SEE ALSO"
io_wait(3), io_canwrite(3), io_eagain(3)

29
io/io_canwrite.3

@ -0,0 +1,29 @@
.TH io_canwrite 3
.SH NAME
io_canwrite \- return a file descriptor that can be written to
.SH SYNTAX
.B #include <io.h>
int64 \fBio_canwrite\fP();
.SH DESCRIPTION
io_canwrite returns the next file descriptor that can be written to.
You have to have used io_wantwrite() on the file descriptor earlier, and
you have to have called io_wait() or io_waituntil().
These functions then keep an internal data structure on which
descriptors were reported writable by the operating system.
Please note that there is no guarantee that you can still write data
without blocking to that descriptor, just that you could when io_wait()
or io_waituntil() were called. Another process could have written
something before you. Look at the result from io_trywrite().
If there are no more descriptors that you can write to without blocking,
io_canwrite will return -1. In this case you should call io_wait() or
io_waituntil() again.
You should only use io_trywrite(3), io_sendfile(3) or iob_send(3) to
write to the file, not plain write(2). If you use write(2) and get
EAGAIN, call io_eagain(3).
.SH "SEE ALSO"
io_wait(3), io_canwrite(3)

11
io/io_check.3

@ -0,0 +1,11 @@
.TH io_check 3
.SH NAME
io_check \- check for new readable or writable descriptors
.SH SYNTAX
.B #include <io.h>
int64 \fBio_check\fP();
.SH DESCRIPTION
io_check is like io_waituntil() with a deadline of now.
.SH "SEE ALSO"
io_wait(3), io_waituntil(3)

24
io/io_close.3

@ -0,0 +1,24 @@
.TH io_close 3
.SH NAME
io_close \- close a file descriptor
.SH SYNTAX
.B #include <io.h>
void \fBio_close\fP(int64 fd);
.SH DESCRIPTION
io_close eliminates the descriptor numbered \fIfd\fR. This usually does not
mean eliminating the object that the descriptor is talking to.
(For example, if a descriptor writes to a named disk file, closing the
descriptor will not remove the file; it simply removes one way of
writing to the file. On the other hand, a pipe disappears as soon as no
descriptors refer to it.)
io_close has no return value; it always succeeds in deallocating the
memory used for the descriptor. If \fIfd\fR is not the number of a
descriptor, io_close has no effect.
io_close() is like close(), but it also removes the descriptor from the
internal io_wait() data structures. If you called io_fd on a
descriptor, you need to use io_close to close it, not just close().
.SH "SEE ALSO"
io_wait(3), io_canwrite(3)

14
io/io_closeonexec.3

@ -0,0 +1,14 @@
.TH io_closeonexec 3
.SH NAME
io_closeonexec \- mark a file descriptor non-inheritable
.SH SYNTAX
.B #include <io.h>
void \fBio_closeonexec\fP(int64 fd);
.SH DESCRIPTION
io_closeonexec marks a file descriptor non-inheritable. It will be
automatically closed if the process executes a different one. The
descriptor will not be automatically closed when you fork() a new child
process, though.
.SH "SEE ALSO"
io_wait(3), io_canwrite(3)

17
io/io_createfile.3

@ -0,0 +1,17 @@
.TH io_createfile 3
.SH NAME
io_createfile \- create a file
.SH SYNTAX
.B #include <io.h>
int \fBio_createfile\fP(int64* d,const char* s);
.SH DESCRIPTION
io_createfile sets d to the number of a new descriptor writing to the disk file
named \fIs\fR, and returns 1. If \fIs\fR already existed, it is truncated to length 0;
otherwise, it is created, with mode 0600.
If something goes wrong, io_createfile sets \fIerrno\fR to indicate the error, and
returns 0; it does not create a new descriptor, and it does not touch d.
(However, it may have truncated or created the file.)
.SH "SEE ALSO"
io_readfile(3)

18
io/io_dontwantread.3

@ -0,0 +1,18 @@
.TH io_dontwantread 3
.SH NAME
io_dontwantread \- signal that you do not want to read from a descriptor
.SH SYNTAX
.B #include <io.h>
void \fBio_dontwantread\fP(int64 fd);
.SH DESCRIPTION
io_dontwantread tells the next io_wait() that you don't want to read
from this descriptor for now. Call io_wantread() again if you change
your mind.
You have to have called io_fd on the descriptor first (io_pipe and
io_socketpair do this for you). Waiting on descriptors only works for
sockets, fifos and pipes. It may also work on devices and TTYs, but
that is platform dependent -- you should not rely on that.
.SH "SEE ALSO"
io_wait(3), io_canread(3), io_wantread(3), io_fd(3)

18
io/io_dontwantwrite.3

@ -0,0 +1,18 @@
.TH io_dontwantwrite 3
.SH NAME
io_dontwantwrite \- signal that you do not want to write to a descriptor
.SH SYNTAX
.B #include <io.h>
void \fBio_dontwantwrite\fP(int64 fd);
.SH DESCRIPTION
io_dontwantwrite tells the next io_wait() that you don't want to write
to this descriptor for now. Call io_wantwrite() again if you change
your mind.
You have to have called io_fd on the descriptor first (io_pipe and
io_socketpair do this for you). Waiting on descriptors only works for
sockets, fifos and pipes. It may also work on devices and TTYs, but
that is platform dependent -- you should not rely on that.
.SH "SEE ALSO"
io_wait(3), io_canwrite(3), io_wantwrite(3), io_fd(3)

20
io/io_eagain.3

@ -0,0 +1,20 @@
.TH io_eagain 3
.SH NAME
io_eagain \- tell io_wait that you got an EAGAIN
.SH SYNTAX
.B #include <io.h>
void \fBio_eagain\fP(int64 fd);
.SH DESCRIPTION
If io_wait() said that you can read from a descriptor, you try to read
from it, and you get EAGAIN, you need to tell io_wait(). This is
important for edge triggered event notification schemes like Linux 2.4's
SIGIO, or you will lose events.
io_tryread(), io_trywrite() and io_sendfile() and iob_send() already
take care of this for you.
This function is only of interest if you integrate io_wait() with legacy
code that uses read/write directly.
.SH "SEE ALSO"
io_wait(3)

19
io/io_fd.3

@ -0,0 +1,19 @@
.TH io_fd 3
.SH NAME
io_fd \- prepare descriptor for io_wait
.SH SYNTAX
.B #include <io.h>
void \fBio_fd\fP(int64 fd);
.SH DESCRIPTION
If you want to use io_canread() and io_canwrite() on a descriptor, you
have to use io_wait() on it first, and io_wait() has to know which
descriptors you are interested in. Use io_fd() for this.
io_pipe and io_socketpair already call io_fd for you.
Waiting on descriptors only works for sockets, fifos and pipes. It may
also work on devices and TTYs, but that is platform dependent -- you
should not rely on that. It does not work on files.
.SH "SEE ALSO"
io_wait(3), io_wantread(3), io_canread(3), io_eagain(3), io_nonblock(3)

14
io/io_finishandshutdown.3

@ -0,0 +1,14 @@
.TH io_finishandshutdown 3
.SH NAME
io_finishandshutdown \- deallocate internal data structures
.SH SYNTAX
.B #include <io.h>
void \fBio_finishandshutdown\fP();
.SH DESCRIPTION
io_finishandshutdown deallocates the internal data structures of
io_wait(). This only makes sense if you run your program in a malloc
checker and want to eliminate the false alarms. Your OS will free data
structures automatically on process termination.
.SH "SEE ALSO"
io_wait(3)

23
io/io_getcookie.3

@ -0,0 +1,23 @@
.TH io_getcookie 3
.SH NAME
io_getcookie \- retrieve cookie
.SH SYNTAX
.B #include <io.h>
void* \fBio_getcookie\fP(int64 fd);
.SH DESCRIPTION
io_getcookie retrieves a cookie (pointer to some anonymous data
structure you associated with this descriptor).
Use io_setcookie(3) to associate a cookie with a descriptor.
If you did not associate a cookie with this descriptor, io_getcookie
returns NULL.
The idea is that you put the state associated with a TCP connection you
serve in a common struct. Then you do not need to have your own data
structure to retrieve the state for a connection, you can just use the
data structure io_wait already maintains. The lookup works in constant
time and should not cause any cache misses.
.SH "SEE ALSO"
io_wait(3), io_setcookie(3)

43
io/io_nonblock.3

@ -0,0 +1,43 @@
.TH io_nonblock 3
.SH NAME
io_nonblock \- switch to non-blocking I/O
.SH SYNTAX
.B #include <io.h>
void \fBio_nonblock\fP(int64 fd);
.SH DESCRIPTION
io_nonblock puts UNIX descriptor fd into ``non-blocking mode.'' Calling
io_nonblock(\fIfd\fR) before io_fd(\fIfd\fR) makes io_tryread and
io_trywrite faster and more efficient.
Actually, current UNIX kernels do not support non-blocking descriptors; they
support non-blocking open files. Furthermore, many programs will break if they
encounter non-blocking mode. This means that you must not use io_nonblock for a
descriptor inherited from another program.
io_nonblock has no return value; it always succeeds. If d is not the number of
a UNIX descriptor, io_nonblock has no effect.
If io_fd is given a descriptor in blocking mode, io_tryread and io_trywrite go
through the following contortions to avoid blocking:
.RS 0
.nr step 1 1
.IP \n[step] 3
Stop if poll says that the descriptor is not ready. Otherwise there's a good
chance, but not a guarantee: even if poll says the descriptor is ready, the
descriptor might not be ready a moment later. (Furthermore, poll can fail on
some systems.)
.IP \n+[step]
Catch SIGALRM. SIGALRM must not be blocked, and must not be used elsewhere in
the program.
.IP \n+[step]
Set an interval timer so that any blocking call will be interrupted by SIGALRM
within 10 milliseconds. (Current UNIX kernels do not allow any shorter
interval.) Of course, this may still mean a 10-millisecond delay.
.RE
If io_fd is given a descriptor in non-blocking mode (or a descriptor for a
regular disk file), io_tryread and io_trywrite avoid these contortions.
.SH "SEE ALSO"
io_wait(3), io_canwrite(3)

19
io/io_passfd.3

@ -0,0 +1,19 @@
.TH io_passfd 3
.SH NAME
io_passfd \- pass a file descriptor over a Unix Domain socket
.SH SYNTAX
.B #include <io.h>
int \fBio_passfd\fP(int64 sock,int64 fd);
.SH DESCRIPTION
io_passfd transfers the file descriptor \fIfd\fR over the Unix Domain
socket \fIsock\fR. This works much like dup(2), only that the copy of
the descriptor appears not in this process but at the other end of the
Unix Domain socket (which therefore must be a process on the same
system).
The peer can then use io_receivefd(3) to receive the file descriptor.
Note that the passed descriptor stays open in the sending process.
.SH "SEE ALSO"
io_receivefd(3)

28
io/io_pipe.3

@ -0,0 +1,28 @@
.TH io_pipe 3
.SH NAME
io_pipe \- create a Unix pipe
.SH SYNTAX
.B #include <io.h>
int \fBio_pipe\fP(int64 pfd[2]);
.SH DESCRIPTION
io_pipe creates a new UNIX ``pipe.'' The pipe can receive data and provide
data; any bytes written to the pipe can then be read from the pipe in the same
order.
A pipe is typically stored in an 8192-byte memory buffer; the exact number
depends on the UNIX kernel. Bytes are written to the end of the buffer and read
from the beginning of the buffer. Once a byte has been read, it is eliminated
from the buffer, making space for another byte to be written; readers cannot
``rewind'' a pipe to read old data. Once 8192 bytes have been written to the
buffer, the pipe will not be ready for further writing until some of the bytes
have been read. Once all the bytes written have been read, the pipe will not be
ready for further reading until more bytes are written.
io_pipe sets \fId\fR[0] to the number of a new descriptor reading from the pipe, and
sets \fId\fR[1] to the number of a new descriptor writing to the pipe. It then
returns 1 to indicate success. If something goes wrong, io_pipe returns 0,
setting errno to indicate the error; in this case it frees any memory that it
allocated for the new pipe, and it leaves \fId\fR alone.
.SH "SEE ALSO"
io_readfile(3), io_createfile(3), io_socketpair(3)

15
io/io_readfile.3

@ -0,0 +1,15 @@
.TH io_readfile 3
.SH NAME
io_readfile \- open a file for reading
.SH SYNTAX
.B #include <io.h>
int \fBio_readfile\fP(int64* d,const char* s);
.SH DESCRIPTION
io_readfile sets d to the number of a new descriptor reading from the
disk file named \fIs\fR, and returns 1.
If something goes wrong, io_readfile sets \fIerrno\fR to indicate the error, and
returns 0; it does not create a new descriptor, and it does not touch d.
.SH "SEE ALSO"
io_readfile(3)

18
io/io_receivefd.3

@ -0,0 +1,18 @@
.TH io_receivefd 3
.SH NAME
io_receivefd \- receive a file descriptor over a Unix Domain socket
.SH SYNTAX
.B #include <io.h>
int64 \fBio_receivefd\fP(int64 sock);
.SH DESCRIPTION
io_receivefd receives a file descriptor from the Unix Domain socket
\fIsock\fR. You can send a descriptor using io_passfd(3).
io_receivefd returns -1 on error or the file descriptor.
The underlying Unix API can send more than one descriptor at the time.
This function expects only one descriptor and will return the first
one if more than one were sent.
.SH "SEE ALSO"
io_passfd(3)

20
io/io_sendfile.3

@ -0,0 +1,20 @@
.TH io_sendfile 3
.SH NAME
io_sendfile \- send data from a file to a socket
.SH SYNTAX
.B #include <io.h>
int64 \fBio_sendfile\fP(int64 sock,int64 fd,uint64 off,uint64 n);
.SH DESCRIPTION
io_sendfile sends data from a file to a socket. This function tries to
do this in a way that allows high quality operating systems to do
zero-copy TCP (serving the data without copying the file contents to
user space or inside kernel space). This function will use special
operating system "sendfile" primitives where available and use memory
mapped I/O otherwise. It should always be faster than using read() and
write() to copy the data yourself.
io_sendfile will return the number of bytes sent. If an error occurred,
it will return -1 for EAGAIN, or -3 otherwise.
.SH "SEE ALSO"
io_wait(3), io_waituntil(3)

8
io/io_sendfile.c

@ -28,7 +28,9 @@ int64 io_sendfile(int64 s,int64 fd,uint64 off,uint64 n) {
#include <sys/socket.h>
int64 io_sendfile(int64 out,int64 in,uint64 off,uint64 bytes) {
return sendfile64(out,in,off,bytes,0,0);
long long r=sendfile64(out,in,off,bytes,0,0);
if (r==-1 && errno!=EAGAIN) r=-3;
return r;
}
#elif defined (__sun__) && defined(__svr4__)
@ -40,7 +42,9 @@ int64 io_sendfile(int64 out,int64 in,uint64 off,uint64 bytes) {
int64 io_sendfile(int64 out,int64 in,uint64 off,uint64 bytes) {
off64_t o=off;
return sendfile64(out,in,&o,bytes);
long long r=sendfile64(out,in,&o,bytes);
if (r==-1 && errno!=EAGAIN) r=-3;
return r;
}
#elif defined(_AIX)

25
io/io_setcookie.3

@ -0,0 +1,25 @@
.TH io_setcookie 3
.SH NAME
io_setcookie \- associate cookie with descriptor
.SH SYNTAX
.B #include <io.h>
void \fBio_setcookie\fP(int64 fd,void* cookie);
.SH DESCRIPTION
io_setcookie associates a cookie (pointer to some anonymous data
structure) with this descriptor. Only one cookie can be associated with
a descriptor.
Use io_getcookie(3) to retrieve the cookie for a descriptor (usually
after io_canread or io_canwrite brought it to your attention).
Please note that io_close does not deallocate your cookie. You need to
do that yourself.
The idea is that you put the state associated with a TCP connection you
serve in a common struct. Then you do not need to have your own data
structure to retrieve the state for a connection, you can just use the
data structure io_wait already maintains. The lookup works in constant
time and should not cause any cache misses.
.SH "SEE ALSO"
io_wait(3), io_getcookie(3)

18
io/io_socketpair.3

@ -0,0 +1,18 @@
.TH io_socketpair 3
.SH NAME
io_socketpair \- create a pair of sockets
.SH SYNTAX
.B #include <io.h>
int \fBio_socketpair\fP(int64 pfd[2]);
.SH DESCRIPTION
io_socketpair creates a new UNIX socket pair and writes both descriptors
to \fId\fR. The socket pair works much like a pipe, but it is
bidirectional (i.e. both descriptors are for reading and writing).
io_socketpair returns 1 to indicate success. If something goes wrong,
io_socketpair returns 0, setting errno to indicate the error; in this
case it frees any memory that it allocated for the new socketpair, and
it leaves \fId\fR alone.
.SH "SEE ALSO"
io_readfile(3), io_createfile(3), io_pipe(3)

18
io/io_timeout.3

@ -0,0 +1,18 @@
.TH io_timeout 3
.SH NAME
io_timeout \- set time limit on descriptor
.SH SYNTAX
.B #include <io.h>
void \fBio_timeout\fP(int64 fd,tai6464 deadline);
.SH DESCRIPTION
The io library keeps track of an optional ``timeout'' for each descriptor. The
timeout is a specific moment in time, stored in a tai6464 variable.
io_timeout(\fId\fR,\fIt\fR) sets the timeout for descriptor \fId\fR to \fIt\fR.
io_timeout has no return value; it always succeeds. (Space to store the timeout
was already allocated as part of the descriptor.) It has no effect if \fId\fR is not
the number of a descriptor.
.SH "SEE ALSO"
io_waituntil(3), io_timeouted(3)

17
io/io_timeouted.3

@ -0,0 +1,17 @@
.TH io_timeouted 3
.SH NAME
io_timeouted \- return a file descriptor over deadline
.SH SYNTAX
.B #include <io.h>
int64 \fBio_timeouted\fP();
.SH DESCRIPTION
io_timeouted returns the next file descriptor that is past it's deadline.
If no descriptors are past their deadlines, it returns -1.
After io_timeouted() returned -1, you should wait a second before
calling it again. Checking for connections past their deadline involves
walking through the whole data structure, which may thrash the CPU
cache needlessly. Treat it as an expensive operation.
.SH "SEE ALSO"
io_wait(3), io_timeout(3)

42
io/io_tryread.3

@ -0,0 +1,42 @@
.TH io_tryread 3
.SH NAME
io_tryread \- read from a descriptor without blocking
.SH SYNTAX
.B #include <io.h>
int \fBio_tryread\fP(int64 fd,char* buf,int64 len);
.SH DESCRIPTION
io_tryread tries to read \fIlen\fR bytes of data from descriptor
\fIfd\fR into buf[0], buf[1], ..., buf[len-1]. (The effects are
undefined if \fIlen\fR is 0 or smaller.) There are several possible
results:
.RS 0
.IP \[bu] 3
o_tryread returns an integer between 1 and \fIlen\fR: This number of bytes was
available for immediate reading; the bytes were read into the beginning
of \fIbuf\fR. Note that this number can be, and often is, smaller than \fIlen\fR;
you must not assume that io_tryread always succeeds in reading exactly
\fIlen\fR bytes.
.IP \[bu]
io_tryread returns 0: No bytes were read, because the descriptor is at
end of file. For example, this descriptor has reached the end of a disk
file, or is reading an empty pipe that has been closed by all writers.
.IP \[bu]
io_tryread returns -1, setting \fIerrno\fR to EAGAIN: No bytes were read,
because the descriptor is not ready. For example, the descriptor is
reading an empty pipe that could still be written to.
.IP \[bu]
io_tryread returns -3, setting \fIerrno\fR to something other than
EAGAIN: No bytes were read, because the read attempt encountered a
persistent error, such as a serious disk failure (EIO), an unreachable
network (ENETUNREACH), or an invalid descriptor number (EBADF).
.RE
io_tryread does not pause waiting for a descriptor that is not ready.
If you want to pause, use io_waitread or io_wait.
You can make io_tryread faster and more efficient by making
the socket non-blocking with io_nonblock().
.SH "SEE ALSO"
io_nonblock(3), io_waitread(3), io_tryreadtimeout(3)

23
io/io_tryreadtimeout.3

@ -0,0 +1,23 @@
.TH io_tryreadtimeout 3
.SH NAME
io_tryreadtimeout \- read from a descriptor without blocking
.SH SYNTAX
.B #include <io.h>
int \fBio_tryreadtimeout\fP(int64 fd,char* buf,int64 len);
.SH DESCRIPTION
io_tryreadtimeout is identical to io_tryread, with the following
exception: if
.RS 0
.IP \[bu] 3
io_tryread returns -1 (the descriptor is not ready for reading), and
.IP \[bu]
the descriptor has a timeout, and
.IP \[bu]
the read attempt was after the descriptor's timeout,
.RE
then io_tryreadtimeout instead returns -2, with errno set to ETIMEDOUT.
.SH "SEE ALSO"
io_nonblock(3), io_waitread(3), io_tryread(3)

51
io/io_trywrite.3

@ -0,0 +1,51 @@
.TH io_trywrite 3
.SH NAME
io_trywrite \- write to a descriptor without blocking
.SH SYNTAX
.B #include <io.h>
int \fBio_trywrite\fP(int64 fd,const char* buf,int64 len);
.SH DESCRIPTION
io_trywrite tries to write \fIlen\fR bytes of data from
buf[0], buf[1], ..., buf[len-1] to descriptor \fIfd\fR. (The effects are
undefined if \fIlen\fR is 0 or smaller.) There are several possible
results:
.RS 0
.IP \[bu] 3
o_trywrite returns an integer between 1 and \fIlen\fR: This number of bytes was
immediately written from the beginning of \fIbuf\fR.
Note that this number can be, and often is, smaller than \fIlen\fR;
you must not assume that io_trywrite always succeeds in writing exactly
\fIlen\fR bytes.
.IP \[bu]
io_trywrite returns -1, setting \fIerrno\fR to EAGAIN: No bytes were
written, because the descriptor is not ready. For example, the
descriptor is writing to a full pipe that could still be read.
.IP \[bu]
io_trywrite returns -3, setting \fIerrno\fR to something other than
EAGAIN: No bytes were written, because the write attempt encountered a
persistent error, such as a serious disk failure (EIO), an unreachable
network (ENETUNREACH), or an invalid descriptor number (EBADF).
.RE
io_trywrite does not pause waiting for a descriptor that is not ready.
If you want to pause, use io_waitread or io_wait.
You can make io_trywrite faster and more efficient by making
the socket non-blocking with io_nonblock().
Once upon a time, many UNIX programs neglected to check the success of
their writes. They would often encounter EPIPE, and would blithely
continue writing, rather than exiting with an appropriate exit code. The
UNIX kernel developers decided to send a SIGPIPE signal, which
terminates the process by default, along with returning EPIPE. This
papers over the problem without fixing it: the same programs ignore
other errors such as EIO. One hopes that the programs have been fixed by
now; kernels nevertheless continue to generate the SIGPIPE signal. The
first time io_trywrite or io_waitwrite is called, it arranges for
SIGPIPE to be ignored. (Technically, for SIGPIPE to be caught by an
empty signal handler, so this doesn't affect child processes.) Do not
use SIGPIPE elsewhere in the program.
.SH "SEE ALSO"
io_nonblock(3), io_waitread(3), io_trywritetimeout(3)

1
io/io_trywrite.c

@ -9,6 +9,7 @@ int64 io_trywrite(int64 d,const char* buf,int64 len) {
struct itimerval old,new;
struct pollfd p;
io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
io_sigpipe();
if (!e) { errno=EBADF; return -3; }
if (!e->nonblock) {
p.fd=d;

23
io/io_trywritetimeout.3

@ -0,0 +1,23 @@
.TH io_trywritetimeout 3
.SH NAME
io_trywritetimeout \- write to a descriptor without blocking
.SH SYNTAX
.B #include <io.h>
int \fBio_trywritetimeout\fP(int64 fd,const char* buf,int64 len);
.SH DESCRIPTION
io_trywritetimeout is identical to io_trywrite, with the following
exception: if
.RS 0
.IP \[bu] 3
io_trywrite returns -1 (the descriptor is not ready for writing), and
.IP \[bu]
the descriptor has a timeout, and
.IP \[bu]
the write attempt was after the descriptor's timeout,
.RE
then io_trywritetimeout instead returns -2, with errno set to ETIMEDOUT.
.SH "SEE ALSO"
io_nonblock(3), io_waitwrite(3), io_trywrite(3)

1
io/io_waitwrite.c

@ -7,6 +7,7 @@ int64 io_waitwrite(int64 d,const char* buf,int64 len) {
long r;
struct pollfd p;
io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
io_sigpipe();
if (!e) { errno=EBADF; return -3; }
if (e->nonblock) {
again:

21
io/io_wantread.3

@ -0,0 +1,21 @@
.TH io_wantread 3
.SH NAME
io_wantread \- signal that you want to read from a descriptor
.SH SYNTAX
.B #include <io.h>
void \fBio_wantread\fP(int64 fd);
.SH DESCRIPTION
io_wantread tells the next io_wait() that you want to read from this
descriptor. Call io_dontwantread() again if you change your mind.
The next time you call io_wait(), it will look whether this descriptor
becomes readable, too. You can then use io_canread() to check whether
the descriptor has become readable.
You have to have called io_fd on the descriptor first (io_pipe and
io_socketpair do this for you). Waiting on descriptors only works for
sockets, fifos and pipes. It may also work on devices and TTYs, but
that is platform dependent -- you should not rely on that.
.SH "SEE ALSO"
io_wait(3), io_canread(3), io_wantread(3), io_fd(3)

21
io/io_wantwrite.3

@ -0,0 +1,21 @@
.TH io_wantwrite 3
.SH NAME
io_wantwrite \- signal that you want to write to a descriptor
.SH SYNTAX
.B #include <io.h>
void \fBio_wantwrite\fP(int64 fd);
.SH DESCRIPTION
io_wantwrite tells the next io_wait() that you want to write to this
descriptor. Call io_dontwantwrite() again if you change your mind.
The next time you call io_wait(), it will look whether this descriptor
becomes writeable, too. You can then use io_canwrite() to check whether
the descriptor has become writable.
You have to have called io_fd on the descriptor first (io_pipe and
io_socketpair do this for you). Waiting on descriptors only works for
sockets, fifos and pipes. It may also work on devices and TTYs, but
that is platform dependent -- you should not rely on that.
.SH "SEE ALSO"
io_wait(3), io_canwrite(3), io_wantwrite(3), io_fd(3)

2
io_internal.h

@ -71,4 +71,6 @@ extern long alt_firstwrite;
int64 io_waituntil2(int64 milliseconds);
void io_sigpipe(void);
#define debug_printf(x)
Loading…
Cancel
Save