aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/nifs/common
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2019-05-07 10:36:56 +0200
committerMicael Karlberg <[email protected]>2019-05-29 18:50:03 +0200
commit51a0daaec83e7e5794d74b7276b2d13f98ba48df (patch)
tree831a4441090fe92115188272e68be81cd7108132 /erts/emulator/nifs/common
parent6ede678f9e7a2ba1b15c276e0e401d7990e88c51 (diff)
downloadotp-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.c104
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;