diff options
author | Per Hedeland <[email protected]> | 2012-01-04 10:57:59 +0100 |
---|---|---|
committer | Henrik Nord <[email protected]> | 2012-01-04 15:24:08 +0100 |
commit | 949ee23d72e4412fed3059c04e395f995388a5fb (patch) | |
tree | 7806efe10aae7c0a03cf4a9bf28d9e494061c730 /erts/emulator/drivers/common | |
parent | 34dca57472ba2f4e82bb03d3713e3318613093bb (diff) | |
download | otp-949ee23d72e4412fed3059c04e395f995388a5fb.tar.gz otp-949ee23d72e4412fed3059c04e395f995388a5fb.tar.bz2 otp-949ee23d72e4412fed3059c04e395f995388a5fb.zip |
Fix returned error from gen_tcp:accept/1,2 when running out of ports
The {error, enfile} return value is badly misleading and confusing for
this case, since the Posix ENFILE errno value has a well-defined meaning
that has nothing to do with Erlang ports. The fix changes the return
value to {error, system_limit}, which is consistent with e.g. various
file(3) functions. inet:format_error/1 has also been updated to support
system_limit in the same manner as file:format_error/1.
Diffstat (limited to 'erts/emulator/drivers/common')
-rw-r--r-- | erts/emulator/drivers/common/inet_drv.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index eeaa4d24ea..7cee4cb928 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -553,6 +553,12 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) # define VALGRIND_MAKE_MEM_DEFINED(ptr,size) #endif +/* + Magic errno value used locally for return of {error, system_limit} + - the emulator definition of SYSTEM_LIMIT is not available here. +*/ +#define INET_ERRNO_SYSTEM_LIMIT (15 << 8) + /*---------------------------------------------------------------------------- ** Interface constants. ** @@ -1645,6 +1651,17 @@ static struct erl_drv_entry dummy_sctp_driver_entry = #endif +/* return lowercase string form of errno value */ +static char *errno_str(int err) +{ + switch (err) { + case INET_ERRNO_SYSTEM_LIMIT: + return "system_limit"; + default: + return erl_errno_id(err); + } +} + /* general control reply function */ static ErlDrvSSizeT ctl_reply(int rep, char* buf, ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) @@ -1665,13 +1682,9 @@ static ErlDrvSSizeT ctl_reply(int rep, char* buf, ErlDrvSizeT len, /* general control error reply function */ static ErlDrvSSizeT ctl_error(int err, char** rbuf, ErlDrvSizeT rsize) { - char response[256]; /* Response buffer. */ - char* s; - char* t; + char* s = errno_str(err); - for (s = erl_errno_id(err), t = response; *s; s++, t++) - *t = tolower(*s); - return ctl_reply(INET_REP_ERROR, response, t-response, rbuf, rsize); + return ctl_reply(INET_REP_ERROR, s, strlen(s), rbuf, rsize); } static ErlDrvSSizeT ctl_xerror(char* xerr, char** rbuf, ErlDrvSizeT rsize) @@ -1683,14 +1696,7 @@ static ErlDrvSSizeT ctl_xerror(char* xerr, char** rbuf, ErlDrvSizeT rsize) static ErlDrvTermData error_atom(int err) { - char errstr[256]; - char* s; - char* t; - - for (s = erl_errno_id(err), t = errstr; *s; s++, t++) - *t = tolower(*s); - *t = '\0'; - return driver_mk_atom(errstr); + return driver_mk_atom(errno_str(err)); } @@ -8050,7 +8056,7 @@ static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args) /* Copy a descriptor, by creating a new port with same settings * as the descriptor desc. - * return NULL on error (ENFILE no ports avail) + * return NULL on error (SYSTEM_LIMIT no ports avail) */ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s, ErlDrvTermData owner, int* err) @@ -8089,7 +8095,7 @@ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s, /* The new port will be linked and connected to the original caller */ port = driver_create_port(port, owner, "tcp_inet", (ErlDrvData) copy_desc); if ((long)port == -1) { - *err = ENFILE; + *err = INET_ERRNO_SYSTEM_LIMIT; FREE(copy_desc); return NULL; } |