Home:ALL Converter>connect() with unix-domain socket and full backlog

connect() with unix-domain socket and full backlog

Ask Time:2013-10-07T17:23:37         Author:Nicholas Wilson

Json Formatter

When the listening backlog is full for STREAM unix-domain sockets, connect(2) fails on most systems with ECONNREFUSED. It would be preferable for it to return EAGAIN.

The reasoning is that it is highly useful to be able to distinguish between the two cases of dead socket (node exists in filesystem, but no process listening anymore) and the case of full backlog. I ran into this problem when porting some Linux software which has some code to clean up dead sockets, but it's a security vulnerability if the code can be tricked into deleting sockets by spamming them to fill up their backlog.

Only Linux returns EAGAIN; AIX, Solaris and Darwin follow BSD behaviour (just tested on each).

POSIX doesn't list EAGAIN as a possible return code from connect() (link), so there may be some compliance issue here.

What's the best route to get everyone to change in line with Linux? I could go and file a bug report with Oracle, Apple, a FreeBSD PR, and fight it out on the mailing lists of each organisation. Or should I pester someone in a standards body (Austin group)? Is it even advisable to try and get everyone to change here, even though the advantage is clear?

Author:Nicholas Wilson,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/19221105/connect-with-unix-domain-socket-and-full-backlog
jxh :

Whether or not you attempt to change the standard, or change how vendors have implemented connect(), I would argue from the point of view of the software, it wouldn't make any difference. ECONNREFUSED and EAGAIN should both be treated as a retry.\n\nDistinguishing between the two cases may allow you to write a more specific diagnostic message on the client, but the retry logic should be the same. Even if the listener doesn't currently exist, it may eventually exist, so a retry should be attempted.\n\ntry_again:\n rc = connect(s, (void *)&addr, sizeof(addr));\n if (rc == 0) return connect_succeeded(s, &addr);\n switch (errno) {\n case EAGAIN:\n case ECONNREFUSED:\n if (should_try_again(retries++)) {\n goto try_again;\n }\n break;\n case EINTR:\n goto try_again;\n default: \n break;\n }\n return connect_failed(s, errno);\n",