summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Fiddaman <andy@omniosce.org>2020-08-12 03:33:17 +0100
committerGitHub <noreply@github.com>2020-08-11 22:33:17 -0400
commit1fc24ed72de4ac8eab15db9b0af90b3e9654262b (patch)
treebb25b3653af04a372a1c404619bb53d3deb24bf1
parent6cf46b2989d19f4276d4e941f35d7daff371ad9b (diff)
downloadillumos-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.c14
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_brand.c25
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);