on the semantics of connect(): EINTR, EALREADY, EINPROGRESS

From: David Madore (david.madore@ens.fr)
Date: 04/22/03


From: david.madore@ens.fr (David Madore)
Date: 22 Apr 2003 18:06:59 GMT

I have a question regarding the semantics of the Unix connect() system
call for blocking (stream) sockets and specifically what happens when
it is interrupted by a signal.

Question: assume fd is a file descriptor referring to a blocking,
SOCK_STREAM socket, say in the PF_INET protocol family. A process
attempts a first call to connect(fd,&name,namelen) and this call is
interrupted by a signal, returning EINTR. In what state is fd then
left? In particular, what happens if connect(fd,&name,namelen) is
immediately re-attempted? I can imagine several possible behaviors:

1. the second call returns immediately with EALREADY, as if the socket
were non-blocking,

2. the second call blocks until connection is achieved (in which case
success is reported) or another signal is received (in which case
EINTR is returned again), or, of course, an error is produced,

3. the second call retries the connection from start, as if the fd had
been closed and another socket had been produced,

4. the second call returns with EISCONN (sort of stupid, but you never
know), or

5. demons fly through your nose (i.e., undefined behavior), or again

6. this simply can't happen because connect() is never unterrupted by
a signal and never returns EINTR.

What does the Norm say (by "the Norm", I mean The Open Group's Single
Unix Specification, version 3, aka SUSv3)? If I read it to the
letter, it prescribes behavior 1 above: indeed, it says "If connect()
is interrupted by a signal that is caught while blocked waiting to
establish a connection, connect() shall fail and set errno to [EINTR],
but the connection request shall not be aborted, and the connection
shall be established asynchronously. [...] The connect() function
shall fail if: [...] [EALREADY] A connection request is already in
progress for the specified socket." There is nothing saying that
EALREADY is used only for non-blocking sockets, so the second call
should fail with EALREADY if the first one returned EINTR, starting an
asynchronous connection attempt: this is behavior 1 in my list above.

However, if we consider the spirit of the norm, then certainly
EINPROGRESS and EALREADY are reserved for non-blocking sockets: a
blocking socket, as its name indicates, should block until success
rather than return a "in progress" or "already in progress" error;
furthermore, it is the general idea that when a system call fails with
EINTR one shoud restart it with the same arguments. This is my
behavior 2. So the spirit of the norm prescribes behavior 2 above, in
my interpretation at least.

One thing is certain: the norm rules out behavior 6 above.

If I read correctly the Linux source code, and summary experiments I
have attempted seem to confirm this, it obeys behavior 2, in
accordance with the reasoning I have just outlined.

The FreeBSD source code, however, seems to think differently: I seem
to see that EALREADY would _never_ be returned by connect() under
FreeBSD, and that EISCONN would be returned when the connection is in
progress. Furthermore, it seems that when connect() is interrupted
and returns EINTR, the connection attempt is aborted, but I'm not sure
I decipher this correctly. Anyway, FreeBSD would have behavior 3 or 4
above, possibly 2, but certainly not 1.

The FreeBSD *man page*, on the other hand, does not document EINTR as
a possible return code for connect(), so that would imply behavior 6.
It documents EALREADY, but only for non-blocking sockets, excluding
behavior 1 again.

The OpenBSD source code, if I read it correctly, makes EALREADY
possible only for non-blocking sockets, again excluding behavior 1.
As for FreeBSD, I'm not sure whether it's 2, 3 or 4. The OpenBSD man
page documents EINTR as possible, so it's not 6, and also EALREADY as
possible only for non-blocking sockets, so 1 is excluded.

The Solaris man page (I don't have access to Solaris source code)
documents EALREADY as only possible for non-blocking sockets, so 1 is
excluded. And EINTR is reported as possible, though the meaning is
unclear, but 6 seems excluded.

This means a lot of confusion.

Does someone have an in-depth experience of what various actual Unixen
do when connect() receives a signal, and how a second connect() call
will react, and what is the right way of programming around this
(assuming non-blocking sockets are not an option)? Is there some way
to file a clarification request on the SUSv3 specification? Also,
what does POSIX say (if anything) in the matter?

Any information on the subject is welcome.

-- 
     David A. Madore
    (david.madore@ens.fr,
     http://www.eleves.ens.fr:8080/home/madore/ )


Relevant Pages

  • Re: Socket communication on multihomed box
    ... LAN route before USB ... The thing is that connection MUST always stay open. ... as for sockets, I'm using native syscalls, not MFC. ... Another thing is that is should work both under Linux and Windows. ...
    (microsoft.public.win32.programmer.networks)
  • Socket communication on multihomed box
    ... I'm building a kind of server which is supposed to handle ... The thing is that connection MUST always stay open. ... as for sockets, I'm using native syscalls, not MFC. ... Another thing is that is should work both under Linux and Windows. ...
    (microsoft.public.win32.programmer.networks)
  • Socket communication on multihomed box
    ... I'm building a kind of server which is supposed to handle ... The thing is that connection MUST always stay open. ... as for sockets, I'm using native syscalls, not MFC. ... Another thing is that is should work both under Linux and Windows. ...
    (comp.programming)
  • Re: Socket leak
    ... MS> Its almost like there are stale sockets. ... it appeared that problem was caused by proftpd. ... connection in passive mode and then exited. ... connection in our system reported by netstat in ESTABLISHED state. ...
    (freebsd-hackers)
  • Re: WHICH WAY DO YOU WIRE A HOUSE*** HELP***!!!!!!
    ... need one good for broadband and have plenty of connections in home ... (office, sky box connection, bedrooms and hall etc) ... the junction box run 5 seperate 2 pair wire to 5 master sockets. ... patch panel sockets paralled, patch the desired bb outlet to the ...
    (uk.telecom.broadband)