File 0495-erts-esock-Socket-accept-leaks-monitors.patch of Package erlang
From 8b0fe45eb56835be02e3ae52469762f8b582b612 Mon Sep 17 00:00:00 2001
From: Micael Karlberg <bmk@erlang.org>
Date: Fri, 9 Sep 2022 19:06:40 +0200
Subject: [PATCH 1/4] [erts|esock] Socket accept leaks monitors
Add missing demonitor after a successful accept.
Also added monitor "init" after a demonitor (to make sure
nothing remains of the previous monitor).
OTP-18240
---
erts/emulator/nifs/common/prim_socket_nif.c | 57 ++++++++++++++++-----
1 file changed, 44 insertions(+), 13 deletions(-)
diff --git a/erts/emulator/nifs/common/prim_socket_nif.c b/erts/emulator/nifs/common/prim_socket_nif.c
index bb067d9f7c..4ac0fc0966 100644
--- a/erts/emulator/nifs/common/prim_socket_nif.c
+++ b/erts/emulator/nifs/common/prim_socket_nif.c
@@ -24,7 +24,8 @@
* The first function is called 'nif_<something>', e.g. nif_open.
* This does the initial validation and argument processing and then
* calls the function that does the actual work. This is called
- * 'esock_<something>'.
+ * 'esock_<something>', e.g. esock_open (actually esock_open2 or
+ * esock_open4).
* ----------------------------------------------------------------------
*
*
@@ -510,6 +511,9 @@ typedef int SOCKET; /* A subset of HANDLE */
#define ESOCK_GET_RESOURCE(ENV, REF, RES) \
enif_get_resource((ENV), (REF), esocks, (RES))
+#define ESOCK_MON2TERM(E, M) \
+ esock_make_monitor_term((E), (M))
+
#define ESOCK_RECV_BUFFER_COUNT_DEFAULT 0
#define ESOCK_RECV_BUFFER_SIZE_DEFAULT 8192
#define ESOCK_RECV_CTRL_BUFFER_SIZE_DEFAULT 1024
@@ -6763,7 +6767,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
ref,
descP->currentAcceptorP,
descP->currentAcceptor.pid,
- esock_make_monitor_term(env, &descP->currentAcceptor.mon),
+ ESOCK_MON2TERM(env, &descP->currentAcceptor.mon),
descP->currentAcceptor.env,
descP->currentAcceptor.ref) );
@@ -6823,9 +6827,8 @@ ERL_NIF_TERM esock_accept(ErlNifEnv* env,
accRef, caller, save_errno);
} else {
/* We got an incoming connection */
- return
- esock_accept_listening_accept(env, descP, sockRef,
- accSock, caller);
+ return esock_accept_listening_accept(env, descP, sockRef,
+ accSock, caller);
}
} else {
@@ -6836,16 +6839,20 @@ ERL_NIF_TERM esock_accept(ErlNifEnv* env,
SSDBG( descP, ("SOCKET", "esock_accept_accepting -> check: "
"is caller current acceptor:"
- "\r\n Caller: %T"
- "\r\n Current: %T"
- "\r\n", caller, descP->currentAcceptor.pid) );
+ "\r\n Caller: %T"
+ "\r\n Current: %T"
+ "\r\n Current Mon: %T"
+ "\r\n",
+ caller,
+ descP->currentAcceptor.pid,
+ ESOCK_MON2TERM(env, &descP->currentAcceptor.mon)) );
if (COMPARE_PIDS(&descP->currentAcceptor.pid, &caller) == 0) {
SSDBG( descP,
("SOCKET",
- "esock_accept_accepting {%d} -> current acceptor\r\n",
- descP->sock) );
+ "esock_accept_accepting {%d} -> current acceptor"
+ "\r\n", descP->sock) );
return esock_accept_accepting_current(env, descP, sockRef, accRef);
@@ -6889,7 +6896,7 @@ ERL_NIF_TERM esock_accept_listening_error(ErlNifEnv* env,
SSDBG( descP,
("SOCKET",
- "esock_accept_listening_error {%d} -> would block\r\n",
+ "esock_accept_listening_error {%d} -> would block - retry\r\n",
descP->sock) );
descP->currentAcceptor.pid = caller;
@@ -6902,8 +6909,20 @@ ERL_NIF_TERM esock_accept_listening_error(ErlNifEnv* env,
descP->currentAcceptor.ref =
CP_TERM(descP->currentAcceptor.env, accRef);
descP->currentAcceptorP = &descP->currentAcceptor;
+
+ SSDBG( descP,
+ ("SOCKET",
+ "esock_accept_listening_error {%d} -> retry for: "
+ "\r\n Current Pid: %T"
+ "\r\n Current Mon: %T"
+ "\r\n",
+ descP->sock,
+ descP->currentAcceptor.pid,
+ ESOCK_MON2TERM(env, &descP->currentAcceptor.mon)) );
+
res = esock_accept_busy_retry(env, descP, sockRef, accRef, NULL);
} else {
+
SSDBG( descP,
("SOCKET",
"esock_accept_listening {%d} -> errno: %d\r\n",
@@ -6981,6 +7000,7 @@ ERL_NIF_TERM esock_accept_accepting_current(ErlNifEnv* env,
/* *** esock_accept_accepting_current_accept ***
+ *
* Handles when the current acceptor succeeded in its accept call -
* handle the new connection.
*/
@@ -7001,6 +7021,12 @@ ERL_NIF_TERM esock_accept_accepting_current_accept(ErlNifEnv* env,
if (esock_accept_accepted(env, descP, sockRef, accSock,
descP->currentAcceptor.pid, &res)) {
+ ESOCK_ASSERT( DEMONP("esock_accept_accepting_current_accept -> "
+ "current acceptor",
+ env, descP, &descP->currentAcceptor.mon) == 0);
+
+ MON_INIT(&descP->currentAcceptor.mon);
+
if (!activate_next_acceptor(env, descP, sockRef)) {
SSDBG( descP,
@@ -7134,9 +7160,13 @@ ERL_NIF_TERM esock_accept_busy_retry(ErlNifEnv* env,
ESOCK_ASSERT( DEMONP("esock_accept_busy_retry - select failed",
env, descP, &descP->currentAcceptor.mon) == 0);
+
+ MON_INIT(&descP->currentAcceptor.mon);
+
/* It is very unlikely that a next acceptor will be able
* to do anything successful, but we will clean the queue
*/
+
if (!activate_next_acceptor(env, descP, sockRef)) {
SSDBG( descP,
("SOCKET",
@@ -14693,6 +14723,7 @@ ERL_NIF_TERM esock_cancel_accept_current(ErlNifEnv* env,
ESOCK_ASSERT( DEMONP("esock_cancel_accept_current -> current acceptor",
env, descP, &descP->currentAcceptor.mon) == 0);
+ MON_INIT(&descP->currentAcceptor.mon);
res = esock_cancel_read_select(env, descP, descP->currentAcceptor.ref);
SSDBG( descP,
@@ -19424,7 +19455,7 @@ int esock_monitor(const char* slogan,
("SOCKET",
"esock_monitor {%d} [%T] %s: monitor ok: %T\r\n",
descP->sock, esock_self(env), slogan,
- esock_make_monitor_term(env, monP)) );
+ ESOCK_MON2TERM(env, monP)) );
}
return res;
@@ -19444,7 +19475,7 @@ int esock_demonitor(const char* slogan,
SSDBG( descP, ("SOCKET",
"esock_demonitor {%d} [%T] %s: try demonitor %T\r\n",
descP->sock, esock_self(env), slogan,
- esock_make_monitor_term(env, monP)) );
+ ESOCK_MON2TERM(env, monP)) );
res = enif_demonitor_process(env, descP, &monP->mon);
esock_monitor_init(monP);
--
2.35.3