diff options
author | Andy Fiddaman <andy@omniosce.org> | 2020-08-12 03:33:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-11 22:33:17 -0400 |
commit | 1fc24ed72de4ac8eab15db9b0af90b3e9654262b (patch) | |
tree | bb25b3653af04a372a1c404619bb53d3deb24bf1 | |
parent | 6cf46b2989d19f4276d4e941f35d7daff371ad9b (diff) | |
download | illumos-joyent-1fc24ed72de4ac8eab15db9b0af90b3e9654262b.tar.gz |
OS-8200 LX: serialise parallel vfork()/clone(LX_CLONE_VFORK) invocations (#321)
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Mike Zeller <mike.zeller@joyent.com>
Approved by: Jason King <jason.king@joyent.com>
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/signal.c | 14 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_brand.c | 25 |
2 files changed, 32 insertions, 7 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/signal.c b/usr/src/lib/brand/lx/lx_brand/common/signal.c index 74abff9c8c..b83a60380d 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/signal.c +++ b/usr/src/lib/brand/lx/lx_brand/common/signal.c @@ -26,6 +26,7 @@ /* * Copyright 2019 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <sys/types.h> @@ -2400,10 +2401,21 @@ lx_signalfd4(int fd, uintptr_t mask, size_t msize, int flags) return (r == -1 ? -errno : r); } +/* + * Since this brackets vfork, we also use it as a synchronisation point to + * prevent multiple vfork() calls occuring in parallel. This is necessary + * because vfork() on illumos is not MT-safe whereas it is on Linux (with + * caveats). + * + * Some real-world applications (java in particular) can run multiple vfork() + * calls in parallel across different threads and they need to be serialised + * in the lx brand. + */ void lx_block_all_signals() { - (void) syscall(SYS_brand, B_BLOCK_ALL_SIGS); + while (syscall(SYS_brand, B_BLOCK_ALL_SIGS) != 0 && errno == EAGAIN) + yield(); } void diff --git a/usr/src/uts/common/brand/lx/os/lx_brand.c b/usr/src/uts/common/brand/lx/os/lx_brand.c index c7e5351778..31bb86cce1 100644 --- a/usr/src/uts/common/brand/lx/os/lx_brand.c +++ b/usr/src/uts/common/brand/lx/os/lx_brand.c @@ -26,6 +26,7 @@ /* * Copyright 2020 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -1876,23 +1877,35 @@ lx_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, (void) lx_start_nfs_lockd(); return (0); - case B_BLOCK_ALL_SIGS: + case B_BLOCK_ALL_SIGS: { + uint_t result = 0; + mutex_enter(&p->p_lock); pd = ptolxproc(p); - pd->l_block_all_signals++; + /* + * This is used to block handling of all signals during vfork() + * or clone(LX_CLONE_VFORK) emulation to match Linux semantics + * and prevent the parent's signal handlers being called before + * they are properly reset. + */ + if (pd->l_block_all_signals != 0) { + result = set_errno(EAGAIN); + } else { + pd->l_block_all_signals = 1; + } mutex_exit(&p->p_lock); - return (0); + return (result); + } case B_UNBLOCK_ALL_SIGS: { - uint_t result; + uint_t result = 0; mutex_enter(&p->p_lock); pd = ptolxproc(p); if (pd->l_block_all_signals == 0) { result = set_errno(EINVAL); } else { - pd->l_block_all_signals--; - result = 0; + pd->l_block_all_signals = 0; } mutex_exit(&p->p_lock); return (result); |