aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/drivers/common
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2018-07-20 14:09:34 +0200
committerErlang/OTP <[email protected]>2018-07-20 14:09:34 +0200
commitade9ba2fbd9b1698fcc583c7c18cf15b5ce23636 (patch)
tree8ff012286efadf00b532688a1d59b68c7b49a16a /erts/emulator/drivers/common
parent857156bcadae45fe112911bd7ca735ac6f3ca9d2 (diff)
parenta9e579341181ed877379de022a261da81fc7cf8c (diff)
downloadotp-ade9ba2fbd9b1698fcc583c7c18cf15b5ce23636.tar.gz
otp-ade9ba2fbd9b1698fcc583c7c18cf15b5ce23636.tar.bz2
otp-ade9ba2fbd9b1698fcc583c7c18cf15b5ce23636.zip
Merge branch 'john/erts/inet-drv-race/OTP-15158/ERL-654' into maint-20
* john/erts/inet-drv-race/OTP-15158/ERL-654: Fix a race condition when generating async operation ids
Diffstat (limited to 'erts/emulator/drivers/common')
-rw-r--r--erts/emulator/drivers/common/inet_drv.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 554c48059f..f6de343f72 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -1018,6 +1018,7 @@ typedef struct {
inet_async_op* oph; /* queue head or NULL */
inet_async_op* opt; /* queue tail or NULL */
inet_async_op op_queue[INET_MAX_ASYNC]; /* call queue */
+ int op_ref; /* queue reference generator */
int active; /* 0 = passive, 1 = active, 2 = active once */
Sint16 active_count; /* counter for {active,N} */
@@ -1268,8 +1269,7 @@ static int packet_inet_output(udp_descriptor* udesc, HANDLE event);
/* convert descriptor pointer to inet_descriptor pointer */
#define INETP(d) (&(d)->inet)
-static int async_ref = 0; /* async reference id generator */
-#define NEW_ASYNC_ID() ((async_ref++) & 0xffff)
+#define NEW_ASYNC_ID(desc) ((desc)->op_ref++ & 0xffff)
/* check for transition from active to passive */
#define INET_CHECK_ACTIVE_TO_PASSIVE(inet) \
@@ -1921,7 +1921,7 @@ static void enq_multi_op(tcp_descriptor *desc, char *buf, int req,
ErlDrvTermData caller, MultiTimerData *timeout,
ErlDrvMonitor *monitorp)
{
- int id = NEW_ASYNC_ID();
+ int id = NEW_ASYNC_ID(INETP(desc));
enq_old_multi_op(desc,id,req,caller,timeout,monitorp);
if (buf != NULL)
put_int16(id, buf);
@@ -1990,7 +1990,7 @@ static int remove_multi_op(tcp_descriptor *desc, int *id_p, int *req_p,
static int enq_async_w_tmo(inet_descriptor* desc, char* buf, int req, unsigned timeout,
ErlDrvMonitor *monitorp)
{
- int id = NEW_ASYNC_ID();
+ int id = NEW_ASYNC_ID(desc);
inet_async_op* opp;
if ((opp = desc->oph) == NULL) /* queue empty */
@@ -8423,6 +8423,7 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol)
desc->delimiter = '\n'; /* line delimiting char */
desc->oph = NULL;
desc->opt = NULL;
+ desc->op_ref = 0;
desc->peer_ptr = NULL;
desc->name_ptr = NULL;