First problem is I have to open a thread to listen on the socket. The library doesn't have main thread so could not use select or poll. Signal model is even worse. The object structure has to be put in global to pass into the event handler.
The real trouble is when I use send() like this:
if (send(sockfd, buf, len, 0) < 0) {
switch (errno) {
case ENOTSOCK:...
break;
case EPIPE:...
break;
...
}
The whole program exits instead of catching the error condition when the peer closes. Something deja vu so I did a quick search. The answer is SIGPIPE. When writing into a peer closed socket, the system send the SIGPIPE to the program. Apparently my sandbox doesn't prepare for the signal so the default behaviour is to exit the whole program.
Don't want to catch the signal because the program is part of a library. Reroute the signal process may cause other parts trouble. Read the man page of send() again. Found the last argument of send(), flags, actually defined MSG_NOSIGNAL to avoid the signal:
MSG_NOSIGNAL (since Linux 2.2)
Requests not to send SIGPIPE on errors on stream oriented sockets when the other end breaks the
connection. The EPIPE error is still returned.
So change the code to:
if (send(sockfd, buf, len, MSG_NOSIGNAL) < 0) {
switch (errno) {
case ENOTSOCK:...
break;
case EPIPE:...
break;
...
}
It works, hooray!
No comments:
Post a Comment