termin...@gmail.com writes:
> On Wednesday, February 13, 2013 10:51:01 PM UTC+2, Barry Margolin wrote:
[...]
>> This is why the default behavior is to use a signal, SIGPIPE, to
>> indicate that the RST was received -- it happens asynchronously, when
>> the RST arrives later. If you disable, ignore, or block the signal, you
>> don't find out about the reset until you perform an I/O operation on the
>> socket after the RST is received; the next operation (or an operation
>> that's blocked on the socket when the RST is received) will report
>> ECONNRESET.
>
> I am still confused about it, but you are saying that:
>
> An attempt by the server to send() after the client has already
> shutdown(SHUT_RDWR) normally results in a RST on the server
> side and would raise SIGPIPE.
>
> By default SIGPIPE kills the process, and frankly from my experience
> a connection reset does not kill my process (either client or
> server).
I don't think the description of SIGPIPE in the text was
correct. SIGPIPE is usually raised when an attempt to send data
accross a 'pipe-like' communication channel was made but the recipient
has gone away. For TCP, this should happen on a write attempt after
the socket was fully closed but not the file descriptor, ie, because a
RST was received (I tested this with AF_UNIX because I don't have the
time to write a more elaborate test program now). ECONNRESET is an
error reported by a read attempt on a connection-oriented socket whose
connection was reset. And this is still something different than
'closing the connection'.
> This raises one more question: if server has 100 connected sockets
> and SIGPIPE is raised, how does server pick the socket with the RST
> ? How would server know it was a socket in the first place, and not
> other file descriptor ?
Not at all, but that's a different question.
> And if SIGPIPE will not kill server, I still have the question: can
> the rest of the input data in the socket buffer be read after the
> RST and the SIGPIPE, if server calls recv() later on its socket ?
For AF_UNIX sockets, yes, at least on Linux[*]. But similar to the
"what if the client disconnected already" proposition, the 'server'
has no way of knowing if the connection was reset until the reset
'occurs' within the TCP stream. This going to happen some time after
the final write of the server because this data needs to travel to the
remote endpoint and the RST must come back. Since either data or RST
could be lost in transmission, this could possibly be a *long* time
after this final write, ie, your question doesn't really make sense.
[*]
---------------------
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main(void)
{
int fds[2], rc, d;
rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
if (rc == -1) {
perror("socketpair");
exit(1);
}
switch (fork()) {
case -1:
perror("fork");
exit(1);
case 0:
close(*fds);
write(fds[1], "ha!", 3);
close(fds[1]);
pause();
}
close(fds[1]);
sleep(1);
signal(SIGPIPE, SIG_IGN);
rc = write(*fds, &d, sizeof(d));
if (rc == -1) perror("write");
rc = read(*fds, &d, sizeof(d));
if (rc == -1) {
perror("read");
exit(1);
}
fprintf(stderr, "read returned %d\n", rc);
return 0;
}