diff options
author | Sverker Eriksson <[email protected]> | 2014-09-30 17:00:37 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2014-09-30 20:52:48 +0200 |
commit | b7801392325784027e93e3488e7e28d596e6b658 (patch) | |
tree | 62d48d5cbf62bac466240a77627a73230942d55f /erts | |
parent | bfc6a9b3325969a7bc1d0c228766537049a4f637 (diff) | |
download | otp-b7801392325784027e93e3488e7e28d596e6b658.tar.gz otp-b7801392325784027e93e3488e7e28d596e6b658.tar.bz2 otp-b7801392325784027e93e3488e7e28d596e6b658.zip |
erts: Fix race between port_set_data, port_get_data and port termination
Always update prt->data with atomic xchg-op.
Check for NULL data to detect racing port terminator.
Use NULL, as THE_NON_VALUE can be a valid pointer on debug VM.
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/erl_bif_port.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 8a622e5e6e..64bd598ba6 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -493,8 +493,8 @@ void erts_cleanup_port_data(Port *prt) { ASSERT(erts_atomic32_read_nob(&prt->state) & ERTS_PORT_SFLGS_INVALID_LOOKUP); - cleanup_old_port_data(erts_smp_atomic_read_nob(&prt->data)); - erts_smp_atomic_set_nob(&prt->data, (erts_aint_t) THE_NON_VALUE); + cleanup_old_port_data(erts_smp_atomic_xchg_nob(&prt->data, + (erts_aint_t) NULL)); } Uint @@ -562,8 +562,14 @@ BIF_RETTYPE port_set_data_2(BIF_ALIST_2) data = erts_smp_atomic_xchg_wb(&prt->data, data); + if (data == (erts_aint_t)NULL) { + /* Port terminated by racing thread */ + data = erts_smp_atomic_xchg_wb(&prt->data, data); + ASSERT(data != (erts_aint_t)NULL); + cleanup_old_port_data(data); + BIF_ERROR(BIF_P, BADARG); + } cleanup_old_port_data(data); - BIF_RET(am_true); } @@ -582,6 +588,8 @@ BIF_RETTYPE port_get_data_1(BIF_ALIST_1) BIF_ERROR(BIF_P, BADARG); data = erts_smp_atomic_read_ddrb(&prt->data); + if (data == (erts_aint_t)NULL) + BIF_ERROR(BIF_P, BADARG); /* Port terminated by racing thread */ if ((data & 0x3) != 0) { res = (Eterm) (UWord) data; |