diff options
author | Sverker Eriksson <[email protected]> | 2014-09-30 17:00:37 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2015-01-21 16:08:28 +0100 |
commit | 51d2888163b230836c16944f54ca3a3840a73ad2 (patch) | |
tree | c4d359576cb0d6f0728745cdb2fd9837d54283a1 | |
parent | 57d819805eb032605c64a0128dd70955d7aa085a (diff) | |
download | otp-51d2888163b230836c16944f54ca3a3840a73ad2.tar.gz otp-51d2888163b230836c16944f54ca3a3840a73ad2.tar.bz2 otp-51d2888163b230836c16944f54ca3a3840a73ad2.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.
-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 f4ab8592ae..2464da6d24 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; |