diff options
author | Micael Karlberg <[email protected]> | 2019-05-07 10:36:56 +0200 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2019-05-29 18:50:03 +0200 |
commit | 51a0daaec83e7e5794d74b7276b2d13f98ba48df (patch) | |
tree | 831a4441090fe92115188272e68be81cd7108132 /erts/emulator/nifs/common | |
parent | 6ede678f9e7a2ba1b15c276e0e401d7990e88c51 (diff) | |
download | otp-51a0daaec83e7e5794d74b7276b2d13f98ba48df.tar.gz otp-51a0daaec83e7e5794d74b7276b2d13f98ba48df.tar.bz2 otp-51a0daaec83e7e5794d74b7276b2d13f98ba48df.zip |
[esock] Found and fixed some weirdness on darwin
Tests on Darwin Kernel Version 18.2.0 reveled some
problems handling connect (on that platform).
It seems that calling connect the second time is not needed
(it results in eisconn), so we needed to handle that case,
which we now do.
Diffstat (limited to 'erts/emulator/nifs/common')
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 104 |
1 files changed, 73 insertions, 31 deletions
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 4394e7bc7c..d24edde1e0 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -4901,17 +4901,17 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, return esock_make_error(env, atom_closed); if (!IS_OPEN(descP)) { - SSDBG( descP, ("SOCKET", "nif_connect -> not open\r\n") ); + SSDBG( descP, ("SOCKET", "nconnect -> not open\r\n") ); return esock_make_error(env, atom_exbadstate); } if (IS_CONNECTED(descP)) { - SSDBG( descP, ("SOCKET", "nif_connect -> already connected\r\n") ); + SSDBG( descP, ("SOCKET", "nconnect -> already connected\r\n") ); return esock_make_error(env, atom_eisconn); } if (IS_CONNECTING(descP) && !is_connector(env, descP)) { - SSDBG( descP, ("SOCKET", "nif_connect -> already connecting\r\n") ); + SSDBG( descP, ("SOCKET", "nconnect -> already connecting\r\n") ); return esock_make_error(env, esock_atom_einval); } @@ -4925,45 +4925,79 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, descP->addrLen); save_errno = sock_errno(); - SSDBG( descP, ("SOCKET", "nif_connect -> connect result: %d, %d\r\n", + SSDBG( descP, ("SOCKET", "nconnect -> connect result: %d, %d\r\n", code, save_errno) ); - if (IS_SOCKET_ERROR(code) && - ((save_errno == ERRNO_BLOCK) || /* Winsock2 */ - (save_errno == EINPROGRESS))) { /* Unix & OSE!! */ - ref = MKREF(env); + if (IS_SOCKET_ERROR(code)) { + switch (save_errno) { + case ERRNO_BLOCK: /* Winsock2 */ + case EINPROGRESS: /* Unix & OSE!! */ + SSDBG( descP, ("SOCKET", "nconnect -> would block => select\r\n") ); - if (IS_CONNECTING(descP)) { - /* Glitch */ - res = esock_make_ok2(env, ref); - } else { + ref = MKREF(env); - /* First time here */ + if (IS_CONNECTING(descP)) { + /* Glitch */ + res = esock_make_ok2(env, ref); + } else { - if (enif_self(env, &descP->connPid) == NULL) - return esock_make_error(env, atom_exself); + /* First time here */ - if (MONP("nconnect -> conn", - env, descP, - &descP->connPid, - &descP->connMon) != 0) - return esock_make_error(env, atom_exmon); - - descP->state = SOCKET_STATE_CONNECTING; - - if ((sres = esock_select_write(env, descP->sock, descP, NULL, - sockRef, ref)) < 0) { - res = esock_make_error(env, - MKT2(env, - esock_atom_select_failed, - MKI(env, sres))); - } else { - res = esock_make_ok2(env, ref); + if (enif_self(env, &descP->connPid) == NULL) + return esock_make_error(env, atom_exself); + + if (MONP("nconnect -> conn", + env, descP, + &descP->connPid, + &descP->connMon) != 0) + return esock_make_error(env, atom_exmon); + + descP->state = SOCKET_STATE_CONNECTING; + + if ((sres = esock_select_write(env, descP->sock, descP, NULL, + sockRef, ref)) < 0) { + res = esock_make_error(env, + MKT2(env, + esock_atom_select_failed, + MKI(env, sres))); + } else { + res = esock_make_ok2(env, ref); + } } + break; + + case EISCONN: + SSDBG( descP, ("SOCKET", "nconnect -> *already* connected\r\n") ); + { + /* This is ***strange*** so make sure */ + int err = 0; + if (!verify_is_connected(descP, &err)) { + descP->state = SOCKET_STATE_OPEN; /* restore state */ + res = esock_make_error_errno(env, err); + } else { + descP->state = SOCKET_STATE_CONNECTED; + /* And just to be on the safe side, reset these */ + enif_set_pid_undefined(&descP->connPid); + DEMONP("nconnect -> connected", + env, descP, &descP->connMon); + descP->isReadable = TRUE; + descP->isWritable = TRUE; + res = esock_atom_ok; + } + } + break; + + default: + SSDBG( descP, ("SOCKET", "nconnect -> other error(1): %d\r\n", + save_errno) ); + res = esock_make_error_errno(env, save_errno); + break; } } else if (code == 0) { /* ok we are connected */ + SSDBG( descP, ("SOCKET", "nconnect -> connected\r\n") ); + descP->state = SOCKET_STATE_CONNECTED; enif_set_pid_undefined(&descP->connPid); DEMONP("nconnect -> connected", env, descP, &descP->connMon); @@ -4971,7 +5005,13 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, descP->isWritable = TRUE; res = esock_atom_ok; + } else { + /* Do we really need this case? */ + + SSDBG( descP, ("SOCKET", "nconnect -> other error(2): %d\r\n", + save_errno) ); + res = esock_make_error_errno(env, save_errno); } @@ -16412,6 +16452,8 @@ char* encode_cmsghdr_data_ipv6(ErlNifEnv* env, #if defined(IPV6_PKTINFO) case IPV6_PKTINFO: { + char* xres; + struct in6_pktinfo* pktInfoP = (struct in6_pktinfo*) dataP; ERL_NIF_TERM ifIndex = MKI(env, pktInfoP->ipi6_ifindex); ERL_NIF_TERM addr; |