From e6ba8d5ede7fb2af9312180459a8a3db0cb081be Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 10 Mar 2010 12:03:09 +0000 Subject: OTP-8475 status lock needed when looking up ioq from async threads Driver threads, such as async threads, using port data locks peeked at the port status field without proper locking when looking up the driver queue. --- erts/emulator/beam/io.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index ad0b909b2a..3309b77086 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -77,15 +77,35 @@ static ERTS_INLINE ErlIOQueue* drvport2ioq(ErlDrvPort drvport) { int ix = (int) drvport; + Uint32 status; + if (ix < 0 || erts_max_ports <= ix) return NULL; - if (erts_port[ix].status & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) - return NULL; - ERTS_LC_ASSERT(!erts_port[ix].port_data_lock - || erts_lc_mtx_is_locked(&erts_port[ix].port_data_lock->mtx)); - ERTS_SMP_LC_ASSERT(erts_port[ix].port_data_lock - || erts_lc_is_port_locked(&erts_port[ix])); - return &erts_port[ix].ioq; + + if (erts_get_scheduler_data()) { + ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(&erts_port[ix])); + ERTS_LC_ASSERT(!erts_port[ix].port_data_lock + || erts_lc_mtx_is_locked( + &erts_port[ix].port_data_lock->mtx)); + + status = erts_port[ix].status; + } + else { + erts_smp_port_state_lock(&erts_port[ix]); + status = erts_port[ix].status; + erts_smp_port_state_unlock(&erts_port[ix]); + + ERTS_LC_ASSERT((status & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) + || erts_port[ix].port_data_lock); + ERTS_LC_ASSERT(!erts_port[ix].port_data_lock + || erts_lc_mtx_is_locked( + &erts_port[ix].port_data_lock->mtx)); + + } + + return ((status & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) + ? NULL + : &erts_port[ix].ioq); } static ERTS_INLINE int -- cgit v1.2.3