summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorraf <none@none>2006-12-13 11:41:29 -0800
committerraf <none@none>2006-12-13 11:41:29 -0800
commit657b1f3d64bcf8eaa2385dba72a6047f089433b2 (patch)
treef39954fcde5cecefa713fa403e7e4b55a83f7c0d /usr/src
parent7b55fa8ea6046becb3b72f8886a503979c322084 (diff)
downloadillumos-joyent-657b1f3d64bcf8eaa2385dba72a6047f089433b2.tar.gz
PSARC 2006/659 fork extensions
6497356 fork extensions --HG-- rename : usr/src/lib/libc/amd64/sys/forkall.s => usr/src/lib/libc/amd64/sys/forkallx.s rename : usr/src/lib/libc/amd64/sys/fork1.s => usr/src/lib/libc/amd64/sys/forkx.s rename : usr/src/lib/libc/amd64/sys/vfork.s => usr/src/lib/libc/amd64/sys/vforkx.s rename : usr/src/lib/libc/i386/sys/forkall.s => usr/src/lib/libc/i386/sys/forkallx.s rename : usr/src/lib/libc/i386/sys/fork1.s => usr/src/lib/libc/i386/sys/forkx.s rename : usr/src/lib/libc/i386/sys/vfork.s => usr/src/lib/libc/i386/sys/vforkx.s rename : usr/src/lib/libc/sparc/sys/forkall.s => usr/src/lib/libc/sparc/sys/forkallx.s rename : usr/src/lib/libc/sparc/sys/fork1.s => usr/src/lib/libc/sparc/sys/forkx.s rename : usr/src/lib/libc/sparc/sys/vfork.s => usr/src/lib/libc/sparc/sys/vforkx.s
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/bsmrecord/audit_record_attr.txt4
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_proc.c11
-rw-r--r--usr/src/cmd/ptools/pflags/pflags.c11
-rw-r--r--usr/src/cmd/truss/actions.c33
-rw-r--r--usr/src/cmd/truss/listopts.c18
-rw-r--r--usr/src/cmd/truss/main.c32
-rw-r--r--usr/src/cmd/truss/print.c26
-rw-r--r--usr/src/cmd/truss/print.h3
-rw-r--r--usr/src/cmd/truss/systable.c50
-rw-r--r--usr/src/head/spawn.h28
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/ptrace.c3
-rw-r--r--usr/src/lib/common/inc/c_synonyms.h3
-rw-r--r--usr/src/lib/libbsm/audit_event.txt2
-rw-r--r--usr/src/lib/libc/amd64/Makefile8
-rw-r--r--usr/src/lib/libc/amd64/sys/forkallx.s (renamed from usr/src/lib/libc/amd64/sys/fork1.s)24
-rw-r--r--usr/src/lib/libc/amd64/sys/forkx.s (renamed from usr/src/lib/libc/amd64/sys/forkall.s)20
-rw-r--r--usr/src/lib/libc/amd64/sys/vforkx.s (renamed from usr/src/lib/libc/amd64/sys/vfork.s)82
-rw-r--r--usr/src/lib/libc/i386/Makefile.com8
-rw-r--r--usr/src/lib/libc/i386/sys/fork1.s46
-rw-r--r--usr/src/lib/libc/i386/sys/forkall.s50
-rw-r--r--usr/src/lib/libc/i386/sys/forkallx.s59
-rw-r--r--usr/src/lib/libc/i386/sys/forkx.s59
-rw-r--r--usr/src/lib/libc/i386/sys/vfork.s121
-rw-r--r--usr/src/lib/libc/i386/sys/vforkx.s141
-rw-r--r--usr/src/lib/libc/inc/mtlib.h1
-rw-r--r--usr/src/lib/libc/inc/synonyms.h4
-rw-r--r--usr/src/lib/libc/inc/thr_uberdata.h7
-rw-r--r--usr/src/lib/libc/port/gen/getutx.c25
-rw-r--r--usr/src/lib/libc/port/gen/syslog.c38
-rw-r--r--usr/src/lib/libc/port/mapfile-vers6
-rw-r--r--usr/src/lib/libc/port/regex/wordexp.c159
-rw-r--r--usr/src/lib/libc/port/stdio/popen.c147
-rw-r--r--usr/src/lib/libc/port/stdio/system.c153
-rw-r--r--usr/src/lib/libc/port/threads/scalls.c60
-rw-r--r--usr/src/lib/libc/port/threads/spawn.c36
-rw-r--r--usr/src/lib/libc/port/threads/thr.c8
-rw-r--r--usr/src/lib/libc/sparc/Makefile8
-rw-r--r--usr/src/lib/libc/sparc/sys/forkallx.s (renamed from usr/src/lib/libc/sparc/sys/forkall.s)28
-rw-r--r--usr/src/lib/libc/sparc/sys/forkx.s (renamed from usr/src/lib/libc/sparc/sys/fork1.s)28
-rw-r--r--usr/src/lib/libc/sparc/sys/vforkx.s (renamed from usr/src/lib/libc/sparc/sys/vfork.s)91
-rw-r--r--usr/src/lib/libc/sparcv9/Makefile8
-rw-r--r--usr/src/lib/libdtrace/common/dt_open.c6
-rw-r--r--usr/src/lib/libdtrace/common/dt_proc.c10
-rw-r--r--usr/src/lib/libdtrace/common/procfs.d.in11
-rw-r--r--usr/src/lib/libdtrace/common/procfs.sed.in15
-rw-r--r--usr/src/lib/libpctx/common/libpctx.c4
-rw-r--r--usr/src/lib/libtnfctl/continue.c17
-rw-r--r--usr/src/pkgdefs/SUNWhea/prototype_com1
-rw-r--r--usr/src/ucbcmd/sbcp/syscalls.list9
-rw-r--r--usr/src/uts/common/c2/audit_event.c30
-rw-r--r--usr/src/uts/common/fs/proc/prsubr.c5
-rw-r--r--usr/src/uts/common/os/exit.c59
-rw-r--r--usr/src/uts/common/os/fork.c60
-rw-r--r--usr/src/uts/common/os/sig.c12
-rw-r--r--usr/src/uts/common/os/sysent.c15
-rw-r--r--usr/src/uts/common/sys/Makefile1
-rw-r--r--usr/src/uts/common/sys/fork.h83
-rw-r--r--usr/src/uts/common/sys/proc.h10
-rw-r--r--usr/src/uts/common/sys/procfs.h4
-rw-r--r--usr/src/uts/common/sys/syscall.h10
-rw-r--r--usr/src/uts/intel/ia32/os/syscall.c5
-rw-r--r--usr/src/uts/intel/os/name_to_sysnum1
-rw-r--r--usr/src/uts/sparc/os/name_to_sysnum1
-rw-r--r--usr/src/uts/sparc/os/syscall.c5
64 files changed, 1294 insertions, 729 deletions
diff --git a/usr/src/cmd/bsmrecord/audit_record_attr.txt b/usr/src/cmd/bsmrecord/audit_record_attr.txt
index 3e6b794719..4b8c1bfe29 100644
--- a/usr/src/cmd/bsmrecord/audit_record_attr.txt
+++ b/usr/src/cmd/bsmrecord/audit_record_attr.txt
@@ -810,10 +810,10 @@ label=AUE_FCNTL
label=AUE_FLOCK
skip=Not used.
-label=AUE_FORK
+label=AUE_FORKALL
format=[arg]1
comment=0, pid, "child PID"
- note=The fork(2) return values are undefined because the audit record
+ note=The forkall(2) return values are undefined because the audit record
note=is produced at the point that the child process is spawned.
# see audit.c
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_proc.c b/usr/src/cmd/mdb/common/mdb/mdb_proc.c
index 52c1ea5ad8..f1be163a42 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_proc.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_proc.c
@@ -444,6 +444,7 @@ pt_post_attach(mdb_tgt_t *t)
(void) mdb_tgt_add_sysexit(t, SYS_forkall, hflag, pt_fork, NULL);
(void) mdb_tgt_add_sysexit(t, SYS_fork1, hflag, pt_fork, NULL);
(void) mdb_tgt_add_sysexit(t, SYS_vfork, hflag, pt_fork, NULL);
+ (void) mdb_tgt_add_sysexit(t, SYS_forksys, hflag, pt_fork, NULL);
(void) mdb_tgt_add_sysexit(t, SYS_exec, hflag, pt_exec, NULL);
(void) mdb_tgt_add_sysexit(t, SYS_execve, hflag, pt_exec, NULL);
@@ -604,7 +605,8 @@ pt_fork(mdb_tgt_t *t, int vid, void *private)
mdb_sespec_t *sep;
int follow_parent = mdb.m_forkmode != MDB_FM_CHILD;
- int is_vfork = psp->pr_what == SYS_vfork;
+ int is_vfork = (psp->pr_what == SYS_vfork ||
+ (psp->pr_what == SYS_forksys && psp->pr_sysarg[0] == 2));
struct ps_prochandle *C;
const lwpstatus_t *csp;
@@ -662,8 +664,11 @@ pt_fork(mdb_tgt_t *t, int vid, void *private)
csp = &Pstatus(C)->pr_lwp;
- if (csp->pr_why != PR_SYSEXIT || (csp->pr_what != SYS_forkall &&
- csp->pr_what != SYS_fork1 && csp->pr_what != SYS_vfork)) {
+ if (csp->pr_why != PR_SYSEXIT ||
+ (csp->pr_what != SYS_forkall &&
+ csp->pr_what != SYS_fork1 &&
+ csp->pr_what != SYS_vfork &&
+ csp->pr_what != SYS_forksys)) {
warn("forked child process %ld did not stop on exit from "
"fork as expected\n", psp->pr_rval1);
}
diff --git a/usr/src/cmd/ptools/pflags/pflags.c b/usr/src/cmd/ptools/pflags/pflags.c
index cdb2feb645..7678ba8b59 100644
--- a/usr/src/cmd/ptools/pflags/pflags.c
+++ b/usr/src/cmd/ptools/pflags/pflags.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -62,11 +63,11 @@ static int rflag; /* Show registers? */
#define LWPFLAGS \
(PR_STOPPED|PR_ISTOP|PR_DSTOP|PR_ASLEEP|PR_PCINVAL|PR_STEP \
- |PR_ASLWP|PR_AGENT|PR_DETACH|PR_DAEMON)
+ |PR_AGENT|PR_DETACH|PR_DAEMON)
#define PROCFLAGS \
- (PR_ISSYS|PR_VFORKP|PR_ORPHAN|PR_FORK|PR_RLC|PR_KLC|PR_ASYNC \
- |PR_BPTADJ|PR_MSACCT|PR_MSFORK|PR_PTRACE)
+ (PR_ISSYS|PR_VFORKP|PR_ORPHAN|PR_NOSIGCHLD|PR_WAITPID \
+ |PR_FORK|PR_RLC|PR_KLC|PR_ASYNC|PR_BPTADJ|PR_MSACCT|PR_MSFORK|PR_PTRACE)
#define ALLFLAGS (LWPFLAGS|PROCFLAGS)
@@ -394,6 +395,10 @@ prflags(int arg)
(void) strcat(str, "|VFORKP");
if (arg & PR_ORPHAN)
(void) strcat(str, "|ORPHAN");
+ if (arg & PR_NOSIGCHLD)
+ (void) strcat(str, "|NOSIGCHLD");
+ if (arg & PR_WAITPID)
+ (void) strcat(str, "|WAITPID");
if (arg & PR_FORK)
(void) strcat(str, "|FORK");
if (arg & PR_RLC)
diff --git a/usr/src/cmd/truss/actions.c b/usr/src/cmd/truss/actions.c
index e57569034d..d0313aee7b 100644
--- a/usr/src/cmd/truss/actions.c
+++ b/usr/src/cmd/truss/actions.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,15 +18,15 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
@@ -470,7 +469,7 @@ sysentry(private_t *pri, int dotrace)
int argprinted = FALSE;
const char *name;
- name = sysname(pri, what, raw ? -1 : subcode);
+ name = sysname(pri, what, raw? -1 : subcode);
grow(pri, strlen(name) + 1);
pri->sys_leng = snprintf(pri->sys_string, pri->sys_ssize,
"%s(", name);
@@ -587,7 +586,9 @@ sysexit(private_t *pri, int dotrace)
if (cflag && istraced) {
(void) mutex_lock(&count_lock);
scp = Cp->syscount[what];
- if (subcode != -1 &&
+ if (what == SYS_forksys && subcode >= 3)
+ scp += subcode - 3;
+ else if (subcode != -1 &&
(what != SYS_open && what != SYS_open64 &&
what != SYS_lwp_create))
scp += subcode;
@@ -599,18 +600,21 @@ sysexit(private_t *pri, int dotrace)
(void) mutex_unlock(&count_lock);
}
+ raw = prismember(&rawout, what);
+
if (!cflag && istraced) {
if ((what == SYS_forkall ||
what == SYS_vfork ||
- what == SYS_fork1) &&
+ what == SYS_fork1 ||
+ what == SYS_forksys) &&
pri->Errno == 0 && pri->Rval2 != 0) {
pri->length &= ~07;
- if (what == SYS_forkall)
- pri->length -= 8;
- else
+ if (strlen(sysname(pri, what, raw? -1 : subcode)) < 6) {
(void) fputc('\t', stdout);
+ pri->length += 8;
+ }
pri->length +=
- 15 + printf("\t(returning as child ...)");
+ 7 + printf("\t(returning as child ...)");
}
if (what == SYS_lwp_create &&
pri->Errno == 0 && pri->Rval1 == 0) {
@@ -630,8 +634,6 @@ sysexit(private_t *pri, int dotrace)
}
pri->length = 0;
- raw = prismember(&rawout, what);
-
if (pri->Errno != 0) { /* error in syscall */
if (istraced) {
if (cflag)
@@ -816,7 +818,8 @@ sysexit(private_t *pri, int dotrace)
if (what == SYS_forkall ||
what == SYS_vfork ||
- what == SYS_fork1) {
+ what == SYS_fork1 ||
+ what == SYS_forksys) {
if (pri->Rval2 == 0) /* child was created */
pri->child = pri->Rval1;
else if (cflag && istraced) /* this is the child */
diff --git a/usr/src/cmd/truss/listopts.c b/usr/src/cmd/truss/listopts.c
index b3f2f60930..b8a4dfabd7 100644
--- a/usr/src/cmd/truss/listopts.c
+++ b/usr/src/cmd/truss/listopts.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,15 +18,15 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-
#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */
#include <stdio.h>
@@ -89,6 +88,7 @@ syslist(char *str, /* string of syscall names */
for (; name; name = strtok_r(NULL, sepr, &lasts)) {
int sys;
int sysx;
+ int sysxx;
int sys64;
char *next;
@@ -101,7 +101,7 @@ syslist(char *str, /* string of syscall names */
}
sys = strtol(name, &next, 0);
- sysx = sys64 = 0;
+ sysx = sysxx = sys64 = 0;
if (sys < 0 || sys > PRMAXSYS || *next != '\0')
sys = 0;
if (sys == 0) {
@@ -211,9 +211,11 @@ syslist(char *str, /* string of syscall names */
case SYS_forkall: /* set all if any */
case SYS_fork1:
case SYS_vfork:
+ case SYS_forksys:
sys = SYS_forkall;
sysx = SYS_fork1;
sys64 = SYS_vfork;
+ sysxx = SYS_forksys;
goto def;
case SYS_exec: /* set both if either */
@@ -264,12 +266,16 @@ syslist(char *str, /* string of syscall names */
prdelset(setp, sys);
if (sysx)
prdelset(setp, sysx);
+ if (sysxx)
+ prdelset(setp, sysxx);
if (sys64)
prdelset(setp, sys64);
} else {
praddset(setp, sys);
if (sysx)
praddset(setp, sysx);
+ if (sysxx)
+ praddset(setp, sysxx);
if (sys64)
praddset(setp, sys64);
}
diff --git a/usr/src/cmd/truss/main.c b/usr/src/cmd/truss/main.c
index 9b2cf3f603..2a20a96a9e 100644
--- a/usr/src/cmd/truss/main.c
+++ b/usr/src/cmd/truss/main.c
@@ -627,7 +627,7 @@ main(int argc, char *argv[])
proc_set_t *set = &grab[i++];
(void) mutex_lock(&truss_lock);
- switch (fork1()) {
+ switch (fork()) {
case -1:
(void) fprintf(stderr,
"%s: cannot fork to control process, pid# %d\n",
@@ -687,6 +687,7 @@ main(int argc, char *argv[])
praddset(&traceeven, SYS_forkall);
praddset(&traceeven, SYS_vfork);
praddset(&traceeven, SYS_fork1);
+ praddset(&traceeven, SYS_forksys);
/* for I/O buffer dumps, force tracing of read()s and write()s */
if (!isemptyset(&readfd)) {
@@ -789,7 +790,7 @@ main(int argc, char *argv[])
}
/*
- * Called from main() and from control() after fork1().
+ * Called from main() and from control() after fork().
*/
void
main_thread(int first)
@@ -1292,8 +1293,12 @@ worker_thread(void *arg)
if (pri->child) { /* controlled process fork()ed */
if (fflag || Dynpat != NULL) {
if (Lsp->pr_why == PR_SYSEXIT &&
- Lsp->pr_what == SYS_vfork)
+ (Lsp->pr_what == SYS_vfork ||
+ (Lsp->pr_what == SYS_forksys &&
+ Lsp->pr_sysarg[0] == 2))) {
is_vfork_child = TRUE;
+ (void) Pstop(Proc, 0);
+ }
if (control(pri, pri->child)) {
(void) mutex_unlock(&truss_lock);
pri->child = 0;
@@ -1314,7 +1319,7 @@ worker_thread(void *arg)
/*
* Here, we are still the parent truss.
- * If the child messed with the breakpoints and
+ * If the child messes with the breakpoints and
* this is vfork(), we have to set them again.
*/
if (Dynpat != NULL && is_vfork_child)
@@ -1334,16 +1339,15 @@ worker_thread(void *arg)
* To recover from vfork, we must catch the lwp
* that issued the vfork() when it returns to user
* level, with all other lwps remaining stopped.
- * For this purpose, we direct all lwps to stop
- * and set the vfork()ing lwp running with the
- * PRSTEP flag. We expect to capture it when
- * it stops again showing PR_FAULTED/FLTTRACE.
+ * For this purpose, we have directed all lwps to
+ * stop and we now set the vfork()ing lwp running
+ * with the PRSTEP flag. We expect to capture it
+ * when it stops again showing PR_FAULTED/FLTTRACE.
* We are holding truss_lock, so no other threads
* in truss will set any other lwps in the victim
* process running.
*/
reset_traps = FALSE;
- (void) Pstop(Proc, 0);
(void) Lsetrun(Lwp, 0, PRSTEP);
do {
(void) Lwait(Lwp, 0);
@@ -1518,6 +1522,7 @@ out:
(void) Psysexit(Proc, SYS_forkall, FALSE);
(void) Psysexit(Proc, SYS_vfork, FALSE);
(void) Psysexit(Proc, SYS_fork1, FALSE);
+ (void) Psysexit(Proc, SYS_forksys, FALSE);
(void) Punsetflags(Proc, PR_FORK);
Psync(Proc);
fflag = 0;
@@ -2366,7 +2371,7 @@ control(private_t *pri, pid_t pid)
while (gps->fork_pid != 0)
(void) cond_wait(&gps->fork_cv, &gps->fork_lock);
gps->fork_pid = getpid(); /* parent pid */
- if ((childpid = fork1()) == -1) {
+ if ((childpid = fork()) == -1) {
(void) printf("%s\t*** Cannot fork() to control process #%d\n",
pri->pname, (int)pid);
Flush();
@@ -2439,13 +2444,6 @@ control(private_t *pri, pid_t pid)
make_pname(pri, 0);
- if (Lsp->pr_why != PR_SYSEXIT ||
- (Lsp->pr_what != SYS_forkall &&
- Lsp->pr_what != SYS_vfork &&
- Lsp->pr_what != SYS_fork1))
- (void) printf("%s\t*** Expected SYSEXIT, fork1,forkall,vfork\n",
- pri->pname);
-
pri->syslast = Psp->pr_stime;
pri->usrlast = Psp->pr_utime;
diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c
index d440a71359..92739f2b1e 100644
--- a/usr/src/cmd/truss/print.c
+++ b/usr/src/cmd/truss/print.c
@@ -79,6 +79,7 @@
#include <sys/tsol/tndb.h>
#include <sys/rctl.h>
#include <sys/rctl_impl.h>
+#include <sys/fork.h>
#include "ramdata.h"
#include "print.h"
#include "proto.h"
@@ -2537,6 +2538,30 @@ prt_rcf(private_t *pri, int raw, long val)
prt_hex(pri, 0, val);
}
+/*
+ * Print forkx() flags
+ */
+void
+prt_fxf(private_t *pri, int raw, long val)
+{
+ char *str;
+
+ if (val == 0)
+ outstring(pri, "0");
+ else if (raw || (val & ~(FORK_NOSIGCHLD | FORK_WAITPID)))
+ prt_hhx(pri, 0, val);
+ else {
+ str = pri->code_buf;
+ *str = '\0';
+ if (val & FORK_NOSIGCHLD)
+ (void) strlcat(str, "|FORK_NOSIGCHLD",
+ sizeof (pri->code_buf));
+ if (val & FORK_WAITPID)
+ (void) strlcat(str, "|FORK_WAITPID",
+ sizeof (pri->code_buf));
+ outstring(pri, str + 1);
+ }
+}
/*
* Array of pointers to print functions, one for each format.
@@ -2635,5 +2660,6 @@ void (* const Print[])() = {
prt_rgf, /* RGF -- print getrctl() flags */
prt_rsf, /* RSF -- print setrctl() flags */
prt_rcf, /* RCF -- print rctlsys_ctl() flags */
+ prt_fxf, /* FXF -- print forkx() flags */
prt_dec, /* HID -- hidden argument, make this the last one */
};
diff --git a/usr/src/cmd/truss/print.h b/usr/src/cmd/truss/print.h
index 3819c4c01e..9a4482139e 100644
--- a/usr/src/cmd/truss/print.h
+++ b/usr/src/cmd/truss/print.h
@@ -132,7 +132,8 @@ extern "C" {
#define RGF 90 /* print rctlsys_get flags */
#define RSF 91 /* print rctlsys_set flags */
#define RCF 92 /* print rctlsys_ctl flags */
-#define HID 93 /* hidden argument, don't print */
+#define FXF 93 /* print forkx flags */
+#define HID 94 /* hidden argument, don't print */
/* make sure HID is always the last member */
/*
diff --git a/usr/src/cmd/truss/systable.c b/usr/src/cmd/truss/systable.c
index bc5d8c49a9..695d0e28c2 100644
--- a/usr/src/cmd/truss/systable.c
+++ b/usr/src/cmd/truss/systable.c
@@ -365,7 +365,7 @@ const struct systable systable[] = {
{"sysinfo", 3, DEC, NOV, INF, RST, DEC}, /* 139 */
{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
{"seteuid", 1, DEC, NOV, DEC}, /* 141 */
-{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"forksys", 2, DEC, NOV, DEC, HHX}, /* 142 */
{"fork1", 0, DEC, NOV}, /* 143 */
{"sigtimedwait", 3, DEC, NOV, HEX, HEX, HEX}, /* 144 */
{"lwp_info", 1, DEC, NOV, HEX}, /* 145 */
@@ -792,27 +792,42 @@ static const struct systable zonetable[] = {
{"zone_enter", 2, DEC, NOV, HID, DEC}, /* 3 */
{"zone_list", 3, DEC, NOV, HID, HEX, HEX}, /* 4 */
{"zone_shutdown", 2, DEC, NOV, HID, DEC}, /* 5 */
-{"zone_lookup", 2, DEC, NOV, HID, STG}, /* 6 */
-{"zone_boot", 2, DEC, NOV, HID, DEC}, /* 7 */
+{"zone_lookup", 2, DEC, NOV, HID, STG}, /* 6 */
+{"zone_boot", 2, DEC, NOV, HID, DEC}, /* 7 */
{"zone_version", 2, HEX, NOV, HID, DEC}, /* 8 */
{"zone_setattr", 5, DEC, NOV, HID, DEC, ZGA, HEX, DEC}, /* 9 */
};
#define NZONECODE (sizeof (zonetable) / sizeof (struct systable))
static const struct systable labeltable[] = {
-{"labelsys", 3, DEC, NOV, HID, HEX, HEX}, /* 0 */
+{"labelsys", 3, DEC, NOV, HID, HEX, HEX}, /* 0 */
{"is_system_labeled", 1, DEC, NOV, HID}, /* 1 */
-{"tnrh", 3, DEC, NOV, HID, TND, HEX}, /* 2 */
-{"tnrhtp", 3, DEC, NOV, HID, TND, HEX}, /* 3 */
-{"tnmlp", 3, DEC, NOV, HID, TND, HEX}, /* 4 */
-{"getlabel", 3, DEC, NOV, HID, STG, HEX}, /* 5 */
-{"fgetlabel", 3, DEC, NOV, HID, DEC, HEX}, /* 6 */
+{"tnrh", 3, DEC, NOV, HID, TND, HEX}, /* 2 */
+{"tnrhtp", 3, DEC, NOV, HID, TND, HEX}, /* 3 */
+{"tnmlp", 3, DEC, NOV, HID, TND, HEX}, /* 4 */
+{"getlabel", 3, DEC, NOV, HID, STG, HEX}, /* 5 */
+{"fgetlabel", 3, DEC, NOV, HID, DEC, HEX}, /* 6 */
};
#define NLABELCODE (sizeof (labeltable) / sizeof (struct systable))
+const struct systable forktable[] = {
+/* parent codes */
+{"forkx", 2, DEC, NOV, HID, FXF}, /* 0 */
+{"forkallx", 2, DEC, NOV, HID, FXF}, /* 1 */
+{"vforkx", 2, DEC, NOV, HID, FXF}, /* 2 */
+/* child codes */
+{"forkx", 0, DEC, NOV}, /* 3 */
+{"forkallx", 0, DEC, NOV}, /* 4 */
+{"vforkx", 0, DEC, NOV}, /* 5 */
+};
+#define NFORKCODE (sizeof (forktable) / sizeof (struct systable))
+
const struct sysalias sysalias[] = {
{ "exit", SYS_exit },
- { "fork", SYS_fork1 },
+ { "fork", SYS_forksys },
+ { "forkx", SYS_forksys },
+ { "forkallx", SYS_forksys },
+ { "vforkx", SYS_forksys },
{ "sbrk", SYS_brk },
{ "getppid", SYS_getpid },
{ "geteuid", SYS_getuid },
@@ -1096,6 +1111,10 @@ subsys(int syscall, int subcode)
if ((unsigned)subcode < NRCTLCODE)
stp = &rctltable[subcode];
break;
+ case SYS_forksys: /* fork family */
+ if ((unsigned)subcode < NFORKCODE)
+ stp = &forktable[subcode];
+ break;
}
}
@@ -1225,6 +1244,12 @@ getsubcode(private_t *pri)
(Lsp->pr_why == PR_SYSEXIT && Lsp->pr_errno == 0 &&
Lsp->pr_rval1 == 0);
break;
+ case SYS_forksys: /* forksys */
+ subcode = arg0;
+ if (Lsp->pr_why == PR_SYSEXIT && Lsp->pr_errno == 0 &&
+ pri->Rval2 != 0) /* this is the child */
+ subcode += 3;
+ break;
case SYS_msgsys: /* msgsys() */
case SYS_semsys: /* semsys() */
case SYS_shmsys: /* shmsys() */
@@ -1308,7 +1333,8 @@ maxsyscalls()
+ NPORTCODE - 1
+ NZONECODE - 1
+ NLABELCODE - 1
- + NRCTLCODE - 1);
+ + NRCTLCODE - 1
+ + NFORKCODE - 1);
}
/*
@@ -1382,6 +1408,8 @@ nsubcodes(int syscall)
return (NLABELCODE);
case SYS_rctlsys:
return (NRCTLCODE);
+ case SYS_forksys:
+ return (NFORKCODE);
default:
return (1);
}
diff --git a/usr/src/head/spawn.h b/usr/src/head/spawn.h
index a33b3adb34..43d44f4638 100644
--- a/usr/src/head/spawn.h
+++ b/usr/src/head/spawn.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,12 +38,20 @@
extern "C" {
#endif
-#define POSIX_SPAWN_RESETIDS 0x01
-#define POSIX_SPAWN_SETPGROUP 0x02
-#define POSIX_SPAWN_SETSIGDEF 0x04
-#define POSIX_SPAWN_SETSIGMASK 0x08
-#define POSIX_SPAWN_SETSCHEDPARAM 0x10
-#define POSIX_SPAWN_SETSCHEDULER 0x20
+/*
+ * flags for posix_spawnattr_setflags()
+ */
+#define POSIX_SPAWN_RESETIDS 0x0001
+#define POSIX_SPAWN_SETPGROUP 0x0002
+#define POSIX_SPAWN_SETSIGDEF 0x0004
+#define POSIX_SPAWN_SETSIGMASK 0x0008
+#define POSIX_SPAWN_SETSCHEDPARAM 0x0010
+#define POSIX_SPAWN_SETSCHEDULER 0x0020
+/*
+ * non-portable Solaris extensions
+ */
+#define POSIX_SPAWN_NOSIGCHLD_NP 0x1000
+#define POSIX_SPAWN_WAITPID_NP 0x2000
typedef struct {
void *__spawn_attrp; /* implementation-private */
diff --git a/usr/src/lib/brand/lx/lx_brand/common/ptrace.c b/usr/src/lib/brand/lx/lx_brand/common/ptrace.c
index d5ec2f94f1..57c564cbb4 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/ptrace.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/ptrace.c
@@ -1800,7 +1800,8 @@ ptrace_catch_fork(pid_t pid, int monitor)
sysp = (sysset_t *)ctlp;
ctlp += sizeof (sysset_t) / sizeof (long);
premptyset(sysp);
- praddset(sysp, SYS_fork1);
+ praddset(sysp, SYS_fork1); /* for old libc */
+ praddset(sysp, SYS_forksys); /* new libc: fork1() is forksys(0, 0) */
*ctlp++ = PCRUN;
*ctlp++ = 0;
*ctlp++ = PCWSTOP;
diff --git a/usr/src/lib/common/inc/c_synonyms.h b/usr/src/lib/common/inc/c_synonyms.h
index 4f58fe6a3c..581f55150f 100644
--- a/usr/src/lib/common/inc/c_synonyms.h
+++ b/usr/src/lib/common/inc/c_synonyms.h
@@ -301,7 +301,9 @@ extern "C" {
#define fmtmsg _fmtmsg
#define fork1 _fork1
#define forkall _forkall
+#define forkallx _forkallx
#define fork _fork
+#define forkx _forkx
#define fpathconf _fpathconf
#define fpclass _fpclass
#define fpgetmask _fpgetmask
@@ -977,6 +979,7 @@ extern "C" {
#define utmpxname _utmpxname
#define utssys _utssys
#define vfork _vfork
+#define vforkx _vforkx
#define vfscanf _vfscanf
#define vhangup _vhangup
#define vscanf _vscanf
diff --git a/usr/src/lib/libbsm/audit_event.txt b/usr/src/lib/libbsm/audit_event.txt
index 784b79eab5..8bb6ee5616 100644
--- a/usr/src/lib/libbsm/audit_event.txt
+++ b/usr/src/lib/libbsm/audit_event.txt
@@ -67,7 +67,7 @@
#
0:AUE_NULL:indir system call:no
1:AUE_EXIT:exit(2):ps
-2:AUE_FORK:fork(2):ps
+2:AUE_FORKALL:forkall(2):ps
# AUE_OPEN is a placeholder and will not be generated
3:AUE_OPEN:open(2) - place holder:no
4:AUE_CREAT:creat(2):fc
diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile
index 8af48c4361..41d5c3004a 100644
--- a/usr/src/lib/libc/amd64/Makefile
+++ b/usr/src/lib/libc/amd64/Makefile
@@ -293,8 +293,8 @@ SYSOBJS= \
_lwp_mutex_unlock.o \
_stack_grow.o \
door.o \
- fork1.o \
- forkall.o \
+ forkx.o \
+ forkallx.o \
fxstat.o \
getcontext.o \
gettimeofday.o \
@@ -308,7 +308,7 @@ SYSOBJS= \
uadmin.o \
umount.o \
uname.o \
- vfork.o \
+ vforkx.o \
xmknod.o \
xstat.o
@@ -1094,7 +1094,7 @@ ASSYMDEP_OBJS= \
asm_subr.o \
getcontext.o \
tls_get_addr.o \
- vfork.o
+ vforkx.o
$(ASSYMDEP_OBJS:%=pics/%): assym.h
diff --git a/usr/src/lib/libc/amd64/sys/fork1.s b/usr/src/lib/libc/amd64/sys/forkallx.s
index 6251fb32ae..dc367d005c 100644
--- a/usr/src/lib/libc/amd64/sys/fork1.s
+++ b/usr/src/lib/libc/amd64/sys/forkallx.s
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -31,18 +31,26 @@
#include "SYS.h"
/*
- * pid = fork1();
+ * pid = __forkallx(flags);
+ *
+ * syscall trap: forksys(1, flags)
*
+ * From the syscall:
* %edx == 0 in parent process, %edx = 1 in child process.
* %eax == pid of child in parent, %eax == pid of parent in child.
+ *
+ * The child gets a zero return value.
+ * The parent gets the pid of the child.
*/
- ENTRY(__fork1)
- SYSTRAP_2RVALS(fork1)
+ ENTRY(__forkallx)
+ movl %edi, %esi
+ movl $1, %edi
+ SYSTRAP_2RVALS(forksys)
SYSCERROR
testl %edx, %edx
jz 1f /* jump if parent */
xorl %eax, %eax /* child, return (0) */
1:
RET
- SET_SIZE(__fork1)
+ SET_SIZE(__forkallx)
diff --git a/usr/src/lib/libc/amd64/sys/forkall.s b/usr/src/lib/libc/amd64/sys/forkx.s
index d9a8258566..afdb99297f 100644
--- a/usr/src/lib/libc/amd64/sys/forkall.s
+++ b/usr/src/lib/libc/amd64/sys/forkx.s
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -31,7 +31,9 @@
#include "SYS.h"
/*
- * pid = forkall();
+ * pid = __forkx(flags);
+ *
+ * syscall trap: forksys(0, flags)
*
* From the syscall:
* %edx == 0 in parent process, %edx = 1 in child process.
@@ -41,12 +43,14 @@
* The parent gets the pid of the child.
*/
- ENTRY(__forkall)
- SYSTRAP_2RVALS(forkall)
+ ENTRY(__forkx)
+ movl %edi, %esi
+ xorl %edi, %edi
+ SYSTRAP_2RVALS(forksys)
SYSCERROR
testl %edx, %edx
jz 1f /* jump if parent */
xorl %eax, %eax /* child, return (0) */
1:
RET
- SET_SIZE(__forkall)
+ SET_SIZE(__forkx)
diff --git a/usr/src/lib/libc/amd64/sys/vfork.s b/usr/src/lib/libc/amd64/sys/vforkx.s
index 3d9f81728c..507518572b 100644
--- a/usr/src/lib/libc/amd64/sys/vfork.s
+++ b/usr/src/lib/libc/amd64/sys/vforkx.s
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,10 +30,26 @@
#include <sys/asm_linkage.h>
+ ANSI_PRAGMA_WEAK(vforkx,function)
ANSI_PRAGMA_WEAK(vfork,function)
#include "SYS.h"
-#include <../assym.h>
+#include <assym.h>
+
+/*
+ * pid = vforkx(flags);
+ * syscall trap: forksys(2, flags)
+ *
+ * pid = vfork();
+ * syscall trap: forksys(2, 0)
+ *
+ * From the syscall:
+ * %edx == 0 in parent process, %edx = 1 in child process.
+ * %eax == pid of child in parent, %eax == pid of parent in child.
+ *
+ * The child gets a zero return value.
+ * The parent gets the pid of the child.
+ */
/*
* The child of vfork() will execute in the parent's address space,
@@ -46,56 +62,55 @@
* don't end up in a signal handler with curthread->ul_vfork set wrong.
*/
- ENTRY(vfork)
- movq 0(%rsp),%r9 /* save %rip in %r9 */
- leaq _sref_(0f),%rax /* arrange for RET to return here */
- movq %rax,0(%rsp)
- ret
-
+ ENTRY_NP(vforkx)
+ movq %rdi, %r8 /* flags */
+ jmp 0f
+ ENTRY_NP(vfork)
+ xorq %r8, %r8 /* flags = 0 */
0:
- movl $MASKSET1, %edx
+ popq %r9 /* save return %rip in %r9 */
+ movl $MASKSET1, %edx /* block all signals */
movl $MASKSET0, %esi
movl $SIG_SETMASK, %edi
__SYSCALL(lwp_sigmask)
- __SYSCALL(vfork)
- jae 2f
+ movq %r8, %rsi /* flags */
+ movl $2, %edi
+ __SYSCALL(forksys) /* vforkx(flags) */
+ jae 1f
/* reconstruct stack before jumping to __cerror */
- call 1f
-1: movq %r9, 0(%rsp)
- pushq %rax /* save the vfork() return value */
+ pushq %r9
+ movq %rax, %r8 /* save the vfork() error number */
movl %fs:UL_SIGMASK+4, %edx /* reinstate signals */
movl %fs:UL_SIGMASK, %esi
movl $SIG_SETMASK, %edi
__SYSCALL(lwp_sigmask)
- popq %rax /* restore the vfork() return value */
+ movq %r8, %rax /* restore the vfork() error number */
jmp __cerror
-2:
+1:
/*
* To determine if we are (still) a child of vfork(), the child
* increments curthread->ul_vfork by one and the parent decrements
* it by one. If the result is zero, then we are not a child of
* vfork(), else we are. We do this to deal with the case of
* a vfork() child calling vfork().
- *
- * %edx is zero if we are the parent, non-zero if we are the child.
*/
cmpl $0, %edx
- jne 3f
+ jne 2f
movl %fs:UL_VFORK, %edx
- cmpl $0, %edx /* don't let it go negative */
- je 4f
- subl $1, %edx /* curthread->ul_vfork--; */
- jmp 4f
-3:
- movl $0, %eax /* zero the return value in the child */
+ cmpl $0, %edx /* don't let it go negative */
+ je 3f
+ subl $1, %edx /* curthread->ul_vfork--; */
+ jmp 3f
+2:
+ xorl %eax, %eax /* zero the return value in the child */
movl %fs:UL_VFORK, %edx
- addl $1, %edx /* curthread->ul_vfork++; */
-4:
+ addl $1, %edx /* curthread->ul_vfork++; */
+3:
movl %edx, %fs:UL_VFORK
/*
* Clear the schedctl interface in both parent and child.
@@ -104,13 +119,14 @@
xorq %rdx, %rdx
movq %rdx, %fs:UL_SCHEDCTL
movq %rdx, %fs:UL_SCHEDCTL_CALLED
- pushq %rax /* save the vfork() return value */
+ movq %rax, %r8 /* save the vfork() return value */
movl %fs:UL_SIGMASK+4, %edx /* reinstate signals */
movl %fs:UL_SIGMASK, %esi
movl $SIG_SETMASK, %edi
__SYSCALL(lwp_sigmask)
- popq %rax /* restore the vfork() return value */
- jmp *%r9 /* jump back to the caller */
+ movq %r8, %rax /* restore the vfork() return value */
+ jmp *%r9 /* jump back to the caller */
SET_SIZE(vfork)
+ SET_SIZE(vforkx)
diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com
index 153937921b..17b3be0244 100644
--- a/usr/src/lib/libc/i386/Makefile.com
+++ b/usr/src/lib/libc/i386/Makefile.com
@@ -315,8 +315,8 @@ SYSOBJS= \
_lwp_mutex_unlock.o \
_stack_grow.o \
door.o \
- fork1.o \
- forkall.o \
+ forkx.o \
+ forkallx.o \
fxstat.o \
getcontext.o \
gettimeofday.o \
@@ -331,7 +331,7 @@ SYSOBJS= \
uadmin.o \
umount.o \
uname.o \
- vfork.o \
+ vforkx.o \
xmknod.o \
xstat.o
@@ -1155,7 +1155,7 @@ ASSYMDEP_OBJS= \
_stack_grow.o \
getcontext.o \
tls_get_addr.o \
- vfork.o
+ vforkx.o
$(ASSYMDEP_OBJS:%=pics/%) := CPPFLAGS += -I.
diff --git a/usr/src/lib/libc/i386/sys/fork1.s b/usr/src/lib/libc/i386/sys/fork1.s
deleted file mode 100644
index ed154666f5..0000000000
--- a/usr/src/lib/libc/i386/sys/fork1.s
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
- .file "%M%"
-
-#include "SYS.h"
-
-/ pid = fork1();
-
-/ %edx == 0 in parent process, %edx = 1 in child process.
-/ %eax == pid of child in parent, %eax == pid of parent in child.
-
- ENTRY(__fork1)
- SYSTRAP_2RVALS(fork1)
- SYSCERROR
- testl %edx, %edx
- jz 1f / jump if parent
- xorl %eax, %eax / child, return (0)
-1:
- RET
- SET_SIZE(__fork1)
diff --git a/usr/src/lib/libc/i386/sys/forkall.s b/usr/src/lib/libc/i386/sys/forkall.s
deleted file mode 100644
index 6a64e45d34..0000000000
--- a/usr/src/lib/libc/i386/sys/forkall.s
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
- .file "%M%"
-
-#include "SYS.h"
-
-/ pid = forkall();
-
-/ From the syscall:
-/ %edx == 0 in parent process, %edx = 1 in child process.
-/ %eax == pid of child in parent, %eax == pid of parent in child.
-/
-/ The child gets a zero return value.
-/ The parent gets the pid of the child.
-
- ENTRY(__forkall)
- SYSTRAP_2RVALS(forkall)
- SYSCERROR
- testl %edx, %edx
- jz 1f / jump if parent
- xorl %eax, %eax / child, return (0)
-1:
- RET
- SET_SIZE(__forkall)
diff --git a/usr/src/lib/libc/i386/sys/forkallx.s b/usr/src/lib/libc/i386/sys/forkallx.s
new file mode 100644
index 0000000000..7cf6b58e1d
--- /dev/null
+++ b/usr/src/lib/libc/i386/sys/forkallx.s
@@ -0,0 +1,59 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+#include "SYS.h"
+
+/*
+ * pid = __forkallx(flags);
+ *
+ * syscall trap: forksys(1, flags)
+ *
+ * From the syscall:
+ * %edx == 0 in parent process, %edx = 1 in child process.
+ * %eax == pid of child in parent, %eax == pid of parent in child.
+ *
+ * The child gets a zero return value.
+ * The parent gets the pid of the child.
+ */
+
+ ENTRY(__forkallx)
+ popl %ecx
+ pushl $1
+ pushl %ecx
+ SYSTRAP_2RVALS(forksys)
+ popl %ecx
+ movl %ecx, 0(%esp)
+ SYSCERROR
+ testl %edx, %edx
+ jz 1f /* jump if parent */
+ xorl %eax, %eax /* child, return (0) */
+1:
+ RET
+ SET_SIZE(__forkallx)
diff --git a/usr/src/lib/libc/i386/sys/forkx.s b/usr/src/lib/libc/i386/sys/forkx.s
new file mode 100644
index 0000000000..9a24c05d32
--- /dev/null
+++ b/usr/src/lib/libc/i386/sys/forkx.s
@@ -0,0 +1,59 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+#include "SYS.h"
+
+/*
+ * pid = __forkx(flags);
+ *
+ * syscall trap: forksys(0, flags)
+ *
+ * From the syscall:
+ * %edx == 0 in parent process, %edx = 1 in child process.
+ * %eax == pid of child in parent, %eax == pid of parent in child.
+ *
+ * The child gets a zero return value.
+ * The parent gets the pid of the child.
+ */
+
+ ENTRY(__forkx)
+ popl %ecx
+ pushl $0
+ pushl %ecx
+ SYSTRAP_2RVALS(forksys)
+ popl %ecx
+ movl %ecx, 0(%esp)
+ SYSCERROR
+ testl %edx, %edx
+ jz 1f /* jump if parent */
+ xorl %eax, %eax /* child, return (0) */
+1:
+ RET
+ SET_SIZE(__forkx)
diff --git a/usr/src/lib/libc/i386/sys/vfork.s b/usr/src/lib/libc/i386/sys/vfork.s
deleted file mode 100644
index cf8d013767..0000000000
--- a/usr/src/lib/libc/i386/sys/vfork.s
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
- .file "%M%"
-
-#include <sys/asm_linkage.h>
-
- ANSI_PRAGMA_WEAK(vfork,function)
-
-#include "SYS.h"
-#include <assym.h>
-
-/ The child of vfork() will execute in the parent's address space,
-/ thereby changing the stack before the parent runs again.
-/ Therefore we have to be careful how we return from vfork().
-/ Pity the poor debugger developer who has to deal with this kludge.
-/
-/ We block all blockable signals while performing the vfork() system call
-/ trap. This enables us to set curthread->ul_vfork safely, so that we
-/ don't end up in a signal handler with curthread->ul_vfork set wrong.
-
- ENTRY(vfork)
- movl 0(%esp),%ecx / save %eip in %ecx
- _prologue_
- leal _sref_(0f),%eax / arrange for RET to return here
- _epilogue_
- movl %eax,0(%esp)
- ret
-
-0:
- pushl $MASKSET1 / block signals
- pushl $MASKSET0
- pushl $SIG_SETMASK
- pushl %ecx
- __SYSCALLINT(lwp_sigmask)
- addl $16, %esp
-
- __SYSCALLINT(vfork)
- jae 2f
-
- / reconstruct stack before jumping to __cerror
- call 1f
-1: movl %ecx,0(%esp)
- pushl %eax / save the vfork() error number
-
- pushl %gs:UL_SIGMASK+4 / reinstate signals
- pushl %gs:UL_SIGMASK
- pushl $SIG_SETMASK
- pushl %ecx
- __SYSCALLINT(lwp_sigmask)
- addl $16, %esp
-
- popl %eax / restore the vfork() error number
- jmp __cerror
-
-2:
- / To determine if we are (still) a child of vfork(), the child
- / increments curthread->ul_vfork by one and the parent decrements
- / it by one. If the result is zero, then we are not a child of
- / vfork(), else we are. We do this to deal with the case of
- / a vfork() child calling vfork().
- /
- / %edx is zero if we are the parent, non-zero if we are the child.
- /
- cmpl $0,%edx
- jne 3f
- movl %gs:UL_VFORK, %edx
- cmpl $0, %edx / don't let it go negative
- je 4f
- subl $1, %edx / curthread->ul_vfork--;
- jmp 4f
-3:
- movl $0,%eax / zero the return value in the child
- movl %gs:UL_VFORK, %edx
- addl $1, %edx / curthread->ul_vfork++;
-4:
- movl %edx, %gs:UL_VFORK
- /
- / Clear the schedctl interface in both parent and child.
- / (The child might have modified the parent.)
- /
- xorl %edx, %edx
- movl %edx, %gs:UL_SCHEDCTL
- movl %edx, %gs:UL_SCHEDCTL_CALLED
- pushl %eax / save the vfork() return value
-
- pushl %gs:UL_SIGMASK+4 / reinstate signals
- pushl %gs:UL_SIGMASK
- pushl $SIG_SETMASK
- pushl %ecx
- __SYSCALLINT(lwp_sigmask)
- addl $16, %esp
-
- popl %eax / restore the vfork() return value
- jmp *%ecx / jump back to the caller
- SET_SIZE(vfork)
diff --git a/usr/src/lib/libc/i386/sys/vforkx.s b/usr/src/lib/libc/i386/sys/vforkx.s
new file mode 100644
index 0000000000..4659498dc5
--- /dev/null
+++ b/usr/src/lib/libc/i386/sys/vforkx.s
@@ -0,0 +1,141 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(vforkx,function)
+ ANSI_PRAGMA_WEAK(vfork,function)
+
+#include "SYS.h"
+#include <assym.h>
+
+/*
+ * pid = vforkx(flags);
+ * syscall trap: forksys(2, flags)
+ *
+ * pid = vfork();
+ * syscall trap: forksys(2, 0)
+ *
+ * From the syscall:
+ * %edx == 0 in parent process, %edx = 1 in child process.
+ * %eax == pid of child in parent, %eax == pid of parent in child.
+ *
+ * The child gets a zero return value.
+ * The parent gets the pid of the child.
+ */
+
+/*
+ * The child of vfork() will execute in the parent's address space,
+ * thereby changing the stack before the parent runs again.
+ * Therefore we have to be careful how we return from vfork().
+ * Pity the poor debugger developer who has to deal with this kludge.
+ *
+ * We block all blockable signals while performing the vfork() system call
+ * trap. This enables us to set curthread->ul_vfork safely, so that we
+ * don't end up in a signal handler with curthread->ul_vfork set wrong.
+ */
+
+ ENTRY_NP(vforkx)
+ movl 4(%esp), %eax /* flags */
+ jmp 0f
+ ENTRY_NP(vfork)
+ xorl %eax, %eax /* flags = 0 */
+0:
+ popl %ecx /* save return %eip in %ecx */
+ pushl %eax /* flags */
+ pushl $MASKSET1 /* block all signals */
+ pushl $MASKSET0
+ pushl $SIG_SETMASK
+ pushl %ecx
+ __SYSCALLINT(lwp_sigmask)
+ addl $16, %esp
+
+ pushl $2
+ pushl %ecx
+ __SYSCALLINT(forksys) /* vforkx(flags) */
+ jae 1f
+
+ /* reconstruct stack before jumping to __cerror */
+ addl $12, %esp
+ pushl %ecx
+ pushl %eax /* save the vfork() error number */
+
+ pushl %gs:UL_SIGMASK+4 /* reinstate signals */
+ pushl %gs:UL_SIGMASK
+ pushl $SIG_SETMASK
+ pushl %ecx
+ __SYSCALLINT(lwp_sigmask)
+ addl $16, %esp
+
+ popl %eax /* restore the vfork() error number */
+ jmp __cerror
+
+1:
+ addl $12, %esp
+ /*
+ * To determine if we are (still) a child of vfork(), the child
+ * increments curthread->ul_vfork by one and the parent decrements
+ * it by one. If the result is zero, then we are not a child of
+ * vfork(), else we are. We do this to deal with the case of
+ * a vfork() child calling vfork().
+ */
+ cmpl $0, %edx
+ jne 2f
+ movl %gs:UL_VFORK, %edx
+ cmpl $0, %edx /* don't let it go negative */
+ je 3f
+ subl $1, %edx /* curthread->ul_vfork--; */
+ jmp 3f
+2:
+ xorl %eax, %eax /* zero the return value in the child */
+ movl %gs:UL_VFORK, %edx
+ addl $1, %edx /* curthread->ul_vfork++; */
+3:
+ movl %edx, %gs:UL_VFORK
+ /*
+ * Clear the schedctl interface in both parent and child.
+ * (The child might have modified the parent.)
+ */
+ xorl %edx, %edx
+ movl %edx, %gs:UL_SCHEDCTL
+ movl %edx, %gs:UL_SCHEDCTL_CALLED
+ pushl %eax /* save the vfork() return value */
+
+ pushl %gs:UL_SIGMASK+4 /* reinstate signals */
+ pushl %gs:UL_SIGMASK
+ pushl $SIG_SETMASK
+ pushl %ecx
+ __SYSCALLINT(lwp_sigmask)
+ addl $16, %esp
+
+ popl %eax /* restore the vfork() return value */
+ jmp *%ecx /* jump back to the caller */
+ SET_SIZE(vfork)
+ SET_SIZE(vforkx)
diff --git a/usr/src/lib/libc/inc/mtlib.h b/usr/src/lib/libc/inc/mtlib.h
index d864e8e75a..629b61ee9b 100644
--- a/usr/src/lib/libc/inc/mtlib.h
+++ b/usr/src/lib/libc/inc/mtlib.h
@@ -97,6 +97,7 @@ extern int _rw_unlock(rwlock_t *);
extern int _thr_main(void);
extern thread_t _thr_self(void);
+extern int _thrp_cancelled(void);
extern void _thr_exit(void *);
extern size_t _thr_min_stack(void);
extern int _thr_kill(thread_t, int);
diff --git a/usr/src/lib/libc/inc/synonyms.h b/usr/src/lib/libc/inc/synonyms.h
index 30f17eb6cb..faa9d33034 100644
--- a/usr/src/lib/libc/inc/synonyms.h
+++ b/usr/src/lib/libc/inc/synonyms.h
@@ -27,7 +27,6 @@
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
#ifndef _LIBC_SYNONYMS_H
#define _LIBC_SYNONYMS_H
@@ -351,7 +350,9 @@ extern "C" {
#define fnmatch _fnmatch
#define fork1 _fork1
#define forkall _forkall
+#define forkallx _forkallx
#define fork _fork
+#define forkx _forkx
#define fpathconf _fpathconf
#define fpclass _fpclass
#define fpgetmask _fpgetmask
@@ -1121,6 +1122,7 @@ extern "C" {
#define uucopy _uucopy
#define uucopystr _uucopystr
#define vfork _vfork
+#define vforkx _vforkx
#define vfscanf _vfscanf
#define vhangup _vhangup
#define vlfmt _vlfmt
diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h
index 2671ac0a69..b5ecc7a1be 100644
--- a/usr/src/lib/libc/inc/thr_uberdata.h
+++ b/usr/src/lib/libc/inc/thr_uberdata.h
@@ -1188,11 +1188,8 @@ extern void _thrp_unwind(void *);
/*
* Prototypes for the strong versions of the interface functions
*/
-extern pid_t _fork(void);
-extern pid_t _fork1(void);
-extern pid_t __fork1(void);
-extern pid_t _forkall(void);
-extern pid_t __forkall(void);
+extern pid_t __forkx(int);
+extern pid_t __forkallx(int);
extern pid_t _private_getpid(void);
extern uid_t _private_geteuid(void);
extern int _kill(pid_t, int);
diff --git a/usr/src/lib/libc/port/gen/getutx.c b/usr/src/lib/libc/port/gen/getutx.c
index c091a27013..255282d406 100644
--- a/usr/src/lib/libc/port/gen/getutx.c
+++ b/usr/src/lib/libc/port/gen/getutx.c
@@ -506,6 +506,7 @@ invoke_utmp_update(const struct utmpx *entryx)
{
extern char **environ;
+ posix_spawnattr_t attr;
int status;
pid_t child;
pid_t w;
@@ -517,7 +518,6 @@ invoke_utmp_update(const struct utmpx *entryx)
char host[sizeof (entryx->ut_host) + 1];
struct utmpx *curx = NULL;
char bin2hex[] = "0123456789ABCDEF";
- sigset_t mask, omask;
unsigned char *cp;
char *argvec[15];
int error;
@@ -566,14 +566,22 @@ invoke_utmp_update(const struct utmpx *entryx)
argvec[14] = NULL;
/*
- * Block SIGCLD while we do this.
- * This avoids having an unexpected SIGCLD sent to the process.
+ * No SIGCHLD, please, and let no one else reap our child.
*/
- (void) sigemptyset(&mask);
- (void) sigaddset(&mask, SIGCLD);
- (void) sigprocmask(SIG_BLOCK, &mask, &omask);
-
- error = posix_spawn(&child, UTMP_UPDATE, NULL, NULL, argvec, environ);
+ error = posix_spawnattr_init(&attr);
+ if (error) {
+ errno = error;
+ goto out;
+ }
+ error = posix_spawnattr_setflags(&attr,
+ POSIX_SPAWN_NOSIGCHLD_NP | POSIX_SPAWN_WAITPID_NP);
+ if (error) {
+ (void) posix_spawnattr_destroy(&attr);
+ errno = error;
+ goto out;
+ }
+ error = posix_spawn(&child, UTMP_UPDATE, NULL, &attr, argvec, environ);
+ (void) posix_spawnattr_destroy(&attr);
if (error) {
errno = error;
goto out;
@@ -610,7 +618,6 @@ invoke_utmp_update(const struct utmpx *entryx)
}
out:
- (void) sigprocmask(SIG_SETMASK, &omask, NULL);
return (curx);
}
diff --git a/usr/src/lib/libc/port/gen/syslog.c b/usr/src/lib/libc/port/gen/syslog.c
index 38d28d772e..487da876e0 100644
--- a/usr/src/lib/libc/port/gen/syslog.c
+++ b/usr/src/lib/libc/port/gen/syslog.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -83,6 +83,7 @@
#include <sys/door.h>
#include <sys/stat.h>
#include <stropts.h>
+#include <sys/fork.h>
#include <sys/wait.h>
#include "libc.h"
@@ -183,8 +184,6 @@ vsyslog(int pri, const char *fmt, va_list ap)
struct log_ctl hdr;
struct strbuf dat;
struct strbuf ctl;
- sigset_t sigs;
- sigset_t osigs;
char timestr[26]; /* hardwired value 26 due to Posix */
size_t taglen;
int olderrno = errno;
@@ -195,6 +194,7 @@ vsyslog(int pri, const char *fmt, va_list ap)
int showpid;
uint32_t msgid;
char *msgid_start, *msgid_end;
+ int nowait;
/*
* Maximum tag length is 256 (the pad in outline) minus the size of the
@@ -358,21 +358,19 @@ vsyslog(int pri, const char *fmt, va_list ap)
clen = strlen(outline) + 1;
- (void) sigemptyset(&sigs);
- (void) sigaddset(&sigs, SIGCHLD);
- (void) sigprocmask(SIG_BLOCK, &sigs, &osigs);
- pid = fork1();
- if (pid == -1) {
- (void) sigprocmask(SIG_SETMASK, &osigs, NULL);
+ nowait = (LogStat & LOG_NOWAIT);
+ pid = forkx(nowait? 0 : (FORK_NOSIGCHLD | FORK_WAITPID));
+ if (pid == -1)
return;
- }
+
if (pid == 0) {
+ sigset_t sigs;
int fd;
- (void) signal(SIGALRM, SIG_DFL);
- (void) sigprocmask(SIG_BLOCK, NULL, &sigs);
- (void) sigdelset(&sigs, SIGALRM);
- (void) sigprocmask(SIG_SETMASK, &sigs, NULL);
+ (void) sigset(SIGALRM, SIG_DFL);
+ (void) sigemptyset(&sigs);
+ (void) sigaddset(&sigs, SIGALRM);
+ (void) sigprocmask(SIG_UNBLOCK, &sigs, NULL);
(void) alarm(5);
if (((fd = open(sysmsg, O_WRONLY)) >= 0) ||
(fd = open(ctty, O_WRONLY)) >= 0) {
@@ -383,9 +381,9 @@ vsyslog(int pri, const char *fmt, va_list ap)
}
_exit(0);
}
- if (!(LogStat & LOG_NOWAIT))
- (void) waitpid(pid, NULL, 0);
- (void) sigprocmask(SIG_SETMASK, &osigs, NULL);
+ if (!nowait)
+ while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
+ continue;
}
/*
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index bafd47ab0e..22227a6413 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -57,6 +57,8 @@ SUNW_1.23 { # SunOS 5.11 (Solaris 11)
door_ucred;
door_unbind;
fdatasync;
+ forkallx;
+ forkx;
lio_listio;
mkdtemp;
_mkdtemp;
@@ -109,6 +111,7 @@ SUNW_1.23 { # SunOS 5.11 (Solaris 11)
timer_settime;
uucopy;
uucopystr;
+ vforkx;
} SUNW_1.22.2;
SUNW_1.22.2 {
@@ -1510,6 +1513,8 @@ SUNWprivate_1.1 {
__fnmatch_std;
_fork1;
_forkall;
+ _forkallx;
+ _forkx;
_fpclass;
_fpgetmask;
_fpgetround;
@@ -2162,6 +2167,7 @@ SUNWprivate_1.1 {
utssys;
_utssys;
_vfork;
+ _vforkx;
_vhangup;
_vsyslog;
_wait3;
diff --git a/usr/src/lib/libc/port/regex/wordexp.c b/usr/src/lib/libc/port/regex/wordexp.c
index fb65534656..117976e9c5 100644
--- a/usr/src/lib/libc/port/regex/wordexp.c
+++ b/usr/src/lib/libc/port/regex/wordexp.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -58,6 +59,7 @@
#include <unistd.h>
#include <wordexp.h>
#include <stdio.h>
+#include <spawn.h>
#include <errno.h>
#define INITIAL 8 /* initial pathv allocation */
@@ -68,6 +70,12 @@ static int append(wordexp_t *, char *);
extern int __xpg4; /* defined in _xpg4.c; 0 if not xpg4-compiled program */
/*
+ * Needs no locking if fetched only once.
+ * See getenv()/putenv()/setenv().
+ */
+extern const char **environ;
+
+/*
* Do word expansion.
* We just pass our arguments to shell with -E option. Note that the
* underlying shell must recognize the -E option, and do the right thing
@@ -76,8 +84,9 @@ extern int __xpg4; /* defined in _xpg4.c; 0 if not xpg4-compiled program */
int
wordexp(const char *word, wordexp_t *wp, int flags)
{
- static char options[9] = "-";
- static char *args[4];
+ char options[9];
+ char *optendp = options;
+ char *argv[4];
const char *path;
wordexp_t wptmp;
size_t si;
@@ -88,9 +97,15 @@ wordexp(const char *word, wordexp_t *wp, int flags)
int status;
int pv[2]; /* pipe from shell stdout */
FILE *fp; /* pipe read stream */
- char *optendp = options+1;
- int serrno, tmpalloc;
+ int tmpalloc;
char *wd = NULL;
+ const char **env = NULL;
+ const char **envp;
+ const char *ev;
+ int n;
+ posix_spawnattr_t attr;
+ posix_spawn_file_actions_t fact;
+ int error;
static const char *sun_path = "/bin/ksh";
static const char *xpg4_path = "/usr/xpg4/bin/sh";
@@ -114,7 +129,7 @@ wordexp(const char *word, wordexp_t *wp, int flags)
/*
* Man page says:
- * 2. All of the calls must set WRDE_DOOFFS, or all must not
+ * 2. All of the calls must set WRDE_DOOFFS, or all must not
* set it.
* Therefore, if it's not set, we_offs will always be reset.
*/
@@ -129,8 +144,7 @@ wordexp(const char *word, wordexp_t *wp, int flags)
if ((flags & WRDE_APPEND) == 0 || (flags & WRDE_REUSE)) {
wptmp.we_wordc = 0;
wptmp.we_wordn = wptmp.we_offs + INITIAL;
- wptmp.we_wordv = (char **)malloc(
- sizeof (char *) * wptmp.we_wordn);
+ wptmp.we_wordv = malloc(sizeof (char *) * wptmp.we_wordn);
if (wptmp.we_wordv == NULL)
return (WRDE_NOSPACE);
wptmp.we_wordp = wptmp.we_wordv + wptmp.we_offs;
@@ -142,6 +156,7 @@ wordexp(const char *word, wordexp_t *wp, int flags)
/*
* Turn flags into shell options
*/
+ *optendp++ = '-';
*optendp++ = (char)0x05; /* ksh -^E */
if (flags & WRDE_UNDEF)
*optendp++ = 'u';
@@ -149,69 +164,89 @@ wordexp(const char *word, wordexp_t *wp, int flags)
*optendp++ = 'N';
*optendp = '\0';
- if (getenv("PWD") == NULL) {
- if ((wd = malloc(PATH_MAX + 4)) == NULL)
+ /*
+ * Make sure PWD is in the environment.
+ */
+ if ((envp = environ) == NULL) { /* can't happen? */
+ ev = NULL;
+ n = 0;
+ } else {
+ for (n = 0; (ev = envp[n]) != NULL; n++) {
+ if (*ev == 'P' && strncmp(ev, "PWD=", 4) == 0)
+ break;
+ }
+ }
+ if (ev == NULL) { /* PWD missing from the environment */
+ /* allocate a new environment */
+ if ((env = malloc((n + 2) * sizeof (char *))) == NULL ||
+ (wd = malloc(PATH_MAX + 4)) == NULL)
goto cleanup;
+ for (i = 0; i < n; i++)
+ env[i] = envp[i];
(void) strcpy(wd, "PWD=");
if (getcwd(&wd[4], PATH_MAX) == NULL)
(void) strcpy(&wd[4], "/");
+ env[i] = wd;
+ env[i + 1] = NULL;
+ envp = env;
+ }
+
+ if ((error = posix_spawnattr_init(&attr)) != 0) {
+ errno = error;
+ goto cleanup;
+ }
+ if ((error = posix_spawn_file_actions_init(&fact)) != 0) {
+ (void) posix_spawnattr_destroy(&attr);
+ errno = error;
+ goto cleanup;
}
/*
* Set up pipe from shell stdout to "fp" for us
*/
- if (pipe(pv) < 0)
+ if (pipe(pv) < 0) {
+ error = errno;
+ (void) posix_spawnattr_destroy(&attr);
+ (void) posix_spawn_file_actions_destroy(&fact);
+ errno = error;
goto cleanup;
+ }
/*
- * Fork/exec shell with -E word
+ * Spawn shell with -E word
*/
-
- if ((pid = fork1()) == -1) {
- serrno = errno;
+ error = posix_spawnattr_setflags(&attr,
+ POSIX_SPAWN_NOSIGCHLD_NP | POSIX_SPAWN_WAITPID_NP);
+ if (error == 0)
+ error = posix_spawn_file_actions_adddup2(&fact, pv[1], 1);
+ if (error == 0 && pv[0] != 1)
+ error = posix_spawn_file_actions_addclose(&fact, pv[0]);
+ if (error == 0 && pv[1] != 1)
+ error = posix_spawn_file_actions_addclose(&fact, pv[1]);
+ if (error == 0 && !(flags & WRDE_SHOWERR))
+ error = posix_spawn_file_actions_addopen(&fact, 2,
+ "/dev/null", O_WRONLY, 0);
+ path = __xpg4 ? xpg4_path : sun_path;
+ argv[0] = strrchr(path, '/') + 1;
+ argv[1] = options;
+ argv[2] = (char *)word;
+ argv[3] = NULL;
+ if (error == 0)
+ error = posix_spawn(&pid, path, &fact, &attr,
+ (char *const *)argv, (char *const *)envp);
+ (void) posix_spawnattr_destroy(&attr);
+ (void) posix_spawn_file_actions_destroy(&fact);
+ (void) close(pv[1]);
+ if (error) {
(void) close(pv[0]);
- (void) close(pv[1]);
- errno = serrno;
+ errno = error;
goto cleanup;
}
- if (pid == 0) { /* child */
- if (wd != NULL) {
- /*
- * fork1 handler takes care of __environ_lock.
- * Thus we can safely call putenv().
- */
- (void) putenv(wd);
- }
-
- (void) dup2(pv[1], 1);
- (void) close(pv[0]);
- (void) close(pv[1]);
-
- if ((flags & WRDE_SHOWERR) == 0) {
- int devnull;
- devnull = open("/dev/null", O_WRONLY);
- (void) dup2(devnull, 2);
- if (devnull != 2)
- (void) close(devnull);
- }
-
- path = __xpg4 ? xpg4_path : sun_path;
- args[0] = strrchr(path, '/') + 1;
- args[1] = options;
- args[2] = (char *)word;
- args[3] = NULL;
-
- (void) execv(path, args);
- _exit(127);
- }
-
- (void) close(pv[1]);
-
if ((fp = fdopen(pv[0], "rF")) == NULL) {
- serrno = errno;
+ error = errno;
(void) close(pv[0]);
- errno = serrno;
+ errno = error;
goto wait_cleanup;
}
@@ -222,8 +257,9 @@ wordexp(const char *word, wordexp_t *wp, int flags)
*/
cp = line = malloc(BUFSZ);
if (line == NULL) {
+ error = errno;
(void) fclose(fp);
- rv = WRDE_NOSPACE;
+ errno = error;
goto wait_cleanup;
}
eob = line + BUFSZ;
@@ -257,19 +293,24 @@ wordexp(const char *word, wordexp_t *wp, int flags)
(void) fclose(fp); /* kill shell if still writing */
wait_cleanup:
- if (waitpid(pid, &status, 0) == -1)
- rv = WRDE_ERRNO;
- else if (rv == 0)
+ while (waitpid(pid, &status, 0) == -1) {
+ if (errno != EINTR) {
+ if (rv == 0)
+ rv = WRDE_ERRNO;
+ break;
+ }
+ }
+ if (rv == 0)
rv = WEXITSTATUS(status); /* shell WRDE_* status */
cleanup:
if (rv == 0)
*wp = wptmp;
- else {
- if (tmpalloc)
- wordfree(&wptmp);
- }
+ else if (tmpalloc)
+ wordfree(&wptmp);
+ if (env)
+ free(env);
if (wd)
free(wd);
/*
diff --git a/usr/src/lib/libc/port/stdio/popen.c b/usr/src/lib/libc/port/stdio/popen.c
index 6168a8c13b..11071de5bc 100644
--- a/usr/src/lib/libc/port/stdio/popen.c
+++ b/usr/src/lib/libc/port/stdio/popen.c
@@ -29,7 +29,6 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-
#pragma weak pclose = _pclose
#pragma weak popen = _popen
@@ -45,6 +44,7 @@
#include <unistd.h>
#include <errno.h>
#include <thread.h>
+#include <pthread.h>
#include <synch.h>
#include <spawn.h>
#include "stdiom.h"
@@ -55,8 +55,6 @@
#define RDR 0
#define WTR 1
-static int _insert_nolock(pid_t, int);
-
extern int __xpg4; /* defined in _xpg4.c; 0 if not xpg4-compiled program */
extern const char **environ;
@@ -69,19 +67,38 @@ typedef struct node {
} node_t;
static node_t *head = NULL;
+static void _insert_nolock(pid_t, int, node_t *);
+/*
+ * Cancellation cleanup handler.
+ * If we were cancelled in waitpid(), create a daemon thread to
+ * reap our abandoned child. No other thread can do this for us.
+ */
+static void
+cleanup(void *arg)
+{
+ extern const sigset_t maskset;
+ extern void *reapchild(void *); /* see port/stdio/system.c */
+
+ (void) thr_sigsetmask(SIG_SETMASK, &maskset, NULL);
+ (void) thr_create(NULL, 0, reapchild, arg, THR_DAEMON, NULL);
+}
FILE *
popen(const char *cmd, const char *mode)
{
int p[2];
pid_t pid;
- int myside, yourside;
+ int myside;
+ int yourside;
+ int fd;
const char *shpath;
FILE *iop;
int stdio;
node_t *curr;
char *argvec[4];
+ node_t *node;
+ posix_spawnattr_t attr;
posix_spawn_file_actions_t fact;
int error;
static const char *sun_path = "/bin/sh";
@@ -89,8 +106,27 @@ popen(const char *cmd, const char *mode)
static const char *shell = "sh";
static const char *sh_flg = "-c";
- if (pipe(p) < 0)
+ if ((node = lmalloc(sizeof (node_t))) == NULL)
+ return (NULL);
+ if ((error = posix_spawnattr_init(&attr)) != 0) {
+ lfree(node, sizeof (node_t));
+ errno = error;
return (NULL);
+ }
+ if ((error = posix_spawn_file_actions_init(&fact)) != 0) {
+ lfree(node, sizeof (node_t));
+ (void) posix_spawnattr_destroy(&attr);
+ errno = error;
+ return (NULL);
+ }
+ if (pipe(p) < 0) {
+ error = errno;
+ lfree(node, sizeof (node_t));
+ (void) posix_spawnattr_destroy(&attr);
+ (void) posix_spawn_file_actions_destroy(&fact);
+ errno = error;
+ return (NULL);
+ }
shpath = __xpg4? xpg4_path : sun_path;
if (access(shpath, X_OK)) /* XPG4 Requirement: */
@@ -103,23 +139,30 @@ popen(const char *cmd, const char *mode)
/* This will fail more quickly if we run out of fds */
if ((iop = fdopen(myside, mode)) == NULL) {
+ error = errno;
+ lfree(node, sizeof (node_t));
+ (void) posix_spawnattr_destroy(&attr);
+ (void) posix_spawn_file_actions_destroy(&fact);
(void) close(yourside);
(void) close(myside);
+ errno = error;
return (NULL);
}
lmutex_lock(&popen_lock);
/* in the child, close all pipes from other popen's */
- if ((error = posix_spawn_file_actions_init(&fact)) != 0) {
- lmutex_unlock(&popen_lock);
- (void) fclose(iop);
- (void) close(yourside);
- errno = error;
- return (NULL);
+ for (curr = head; curr != NULL && error == 0; curr = curr->next) {
+ /*
+ * These conditions may apply if a previous iob returned
+ * by popen() was closed with fclose() rather than pclose(),
+ * or if close(fileno(iob)) was called.
+ * Accommodate these programming error.
+ */
+ if ((fd = curr->fd) != myside && fd != yourside &&
+ fcntl(fd, F_GETFD) >= 0)
+ error = posix_spawn_file_actions_addclose(&fact, fd);
}
- for (curr = head; curr != NULL && error == 0; curr = curr->next)
- error = posix_spawn_file_actions_addclose(&fact, curr->fd);
if (error == 0)
error = posix_spawn_file_actions_addclose(&fact, myside);
if (yourside != stdio) {
@@ -130,8 +173,13 @@ popen(const char *cmd, const char *mode)
error = posix_spawn_file_actions_addclose(&fact,
yourside);
}
+ if (error == 0)
+ error = posix_spawnattr_setflags(&attr,
+ POSIX_SPAWN_NOSIGCHLD_NP | POSIX_SPAWN_WAITPID_NP);
if (error) {
lmutex_unlock(&popen_lock);
+ lfree(node, sizeof (node_t));
+ (void) posix_spawnattr_destroy(&attr);
(void) posix_spawn_file_actions_destroy(&fact);
(void) fclose(iop);
(void) close(yourside);
@@ -142,16 +190,19 @@ popen(const char *cmd, const char *mode)
argvec[1] = (char *)sh_flg;
argvec[2] = (char *)cmd;
argvec[3] = NULL;
- error = posix_spawn(&pid, shpath, &fact, NULL,
+ error = posix_spawn(&pid, shpath, &fact, &attr,
(char *const *)argvec, (char *const *)environ);
+ (void) posix_spawnattr_destroy(&attr);
(void) posix_spawn_file_actions_destroy(&fact);
-
(void) close(yourside);
- if ((errno = error) != 0 || _insert_nolock(pid, myside) == -1) {
+ if (error) {
lmutex_unlock(&popen_lock);
+ lfree(node, sizeof (node_t));
(void) fclose(iop);
+ errno = error;
return (NULL);
}
+ _insert_nolock(pid, myside, node);
lmutex_unlock(&popen_lock);
@@ -171,33 +222,63 @@ pclose(FILE *ptr)
/* mark this pipe closed */
(void) fclose(ptr);
- if (pid == -1)
+ if (pid <= 0) {
+ errno = ECHILD;
return (-1);
+ }
+
+ /*
+ * pclose() is a cancellation point.
+ * Call waitpid_cancel() rather than _waitpid() to make
+ * sure that we actually perform the cancellation logic.
+ *
+ * If we have already been cancelled (pclose() was called from
+ * a cancellation cleanup handler), attempt to reap the process
+ * w/o waiting, and if that fails just call cleanup(pid).
+ */
+
+ if (_thrp_cancelled()) {
+ if (waitpid(pid, &status, WNOHANG) == pid)
+ return (status);
+ cleanup((void *)(uintptr_t)pid);
+ errno = ECHILD;
+ return (-1);
+ }
- while (waitpid(pid, &status, 0) < 0) {
- /* If waitpid fails with EINTR, restart the waitpid call */
+ pthread_cleanup_push(cleanup, (void *)(uintptr_t)pid);
+ while (waitpid_cancel(pid, &status, 0) < 0) {
if (errno != EINTR) {
status = -1;
break;
}
}
+ pthread_cleanup_pop(0);
return (status);
}
-static int
-_insert_nolock(pid_t pid, int fd)
+static void
+_insert_nolock(pid_t pid, int fd, node_t *new)
{
node_t *prev;
node_t *curr;
- node_t *new;
- for (prev = curr = head; curr != NULL; curr = curr->next)
+ for (prev = curr = head; curr != NULL; curr = curr->next) {
+ /*
+ * curr->fd can equal fd if a previous iob returned by
+ * popen() was closed with fclose() rather than pclose(),
+ * or if close(fileno(iob)) was called.
+ * Accommodate this programming error.
+ */
+ if (curr->fd == fd) {
+ (void) waitpid(curr->pid, NULL, WNOHANG);
+ curr->pid = pid;
+ lfree(new, sizeof (node_t));
+ return;
+ }
prev = curr;
-
- if ((new = lmalloc(sizeof (node_t))) == NULL)
- return (-1);
+ }
new->pid = pid;
new->fd = fd;
@@ -207,8 +288,6 @@ _insert_nolock(pid_t pid, int fd)
head = new;
else
prev->next = new;
-
- return (0);
}
/*
@@ -217,13 +296,16 @@ _insert_nolock(pid_t pid, int fd)
int
_insert(pid_t pid, int fd)
{
- int rc;
+ node_t *node;
+
+ if ((node = lmalloc(sizeof (node_t))) == NULL)
+ return (-1);
lmutex_lock(&popen_lock);
- rc = _insert_nolock(pid, fd);
+ _insert_nolock(pid, fd, node);
lmutex_unlock(&popen_lock);
- return (rc);
+ return (0);
}
@@ -242,10 +324,9 @@ _delete(int fd)
head = curr->next;
else
prev->next = curr->next;
-
+ lmutex_unlock(&popen_lock);
pid = curr->pid;
lfree(curr, sizeof (node_t));
- lmutex_unlock(&popen_lock);
return (pid);
}
prev = curr;
diff --git a/usr/src/lib/libc/port/stdio/system.c b/usr/src/lib/libc/port/stdio/system.c
index b641e6592e..707134751d 100644
--- a/usr/src/lib/libc/port/stdio/system.c
+++ b/usr/src/lib/libc/port/stdio/system.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -30,7 +29,6 @@
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
#include "synonyms.h"
#include "mtlib.h"
#include <sys/types.h>
@@ -41,6 +39,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <memory.h>
+#include <thread.h>
#include <pthread.h>
#include <errno.h>
#include <synch.h>
@@ -50,50 +49,82 @@
extern const char **environ;
extern int __xpg4; /* defined in _xpg4.c; 0 if not xpg4-compiled program */
+extern const sigset_t maskset; /* all maskable signals */
static mutex_t sys_lock = DEFAULTMUTEX; /* protects the following */
static uint_t sys_count = 0; /* number of threads in system() */
-static struct sigaction sys_ibuf; /* SIGINT */
-static struct sigaction sys_qbuf; /* SIGQUIT */
-static struct sigaction sys_cbuf; /* SIGCHLD */
+static struct sigaction sys_ibuf; /* saved SIGINT sigaction */
+static struct sigaction sys_qbuf; /* saved SIGQUIT sigaction */
+static struct sigaction ignore = {0, {SIG_IGN}, {0}};
+
+/*
+ * Things needed by the cancellation cleanup handler.
+ */
+typedef struct {
+ sigset_t savemask; /* saved signal mask */
+ pid_t pid; /* if nonzero, the child's pid */
+} cleanup_t;
+
+/*
+ * Daemon thread whose sole function is to reap an abandoned child.
+ * Also invoked from pclose() (see port/stdio/popen.c).
+ */
+void *
+reapchild(void *arg)
+{
+ pid_t pid = (pid_t)(uintptr_t)arg;
+
+ while (waitpid(pid, NULL, 0) == -1) {
+ if (errno != EINTR)
+ break;
+ }
+ return (NULL);
+}
/*
* Cancellation cleanup handler.
+ * If we were cancelled in waitpid(), create a daemon thread to
+ * reap our abandoned child. No other thread can do this for us.
+ * It would be better if there were a system call to disinherit
+ * a child process (give it to init, just as though we exited).
*/
static void
cleanup(void *arg)
{
- sigset_t *savemaskp = arg;
+ cleanup_t *cup = arg;
+
+ if (cup->pid != 0) { /* we were cancelled; abandoning our pid */
+ (void) thr_sigsetmask(SIG_SETMASK, &maskset, NULL);
+ (void) thr_create(NULL, 0,
+ reapchild, (void *)(uintptr_t)cup->pid,
+ THR_DAEMON, NULL);
+ }
lmutex_lock(&sys_lock);
if (--sys_count == 0) { /* leaving system() */
/*
- * There are no remaining threads in system(),
- * so restore the several signal actions.
+ * There are no remaining threads in system(), so
+ * restore the SIGINT and SIGQUIT signal actions.
*/
(void) sigaction(SIGINT, &sys_ibuf, NULL);
(void) sigaction(SIGQUIT, &sys_qbuf, NULL);
- if (sys_cbuf.sa_handler == SIG_IGN ||
- (sys_cbuf.sa_flags & SA_NOCLDWAIT))
- (void) sigaction(SIGCHLD, &sys_cbuf, NULL);
}
lmutex_unlock(&sys_lock);
- (void) sigprocmask(SIG_SETMASK, savemaskp, NULL);
+
+ (void) thr_sigsetmask(SIG_SETMASK, &cup->savemask, NULL);
}
int
system(const char *cmd)
{
- pid_t pid;
+ cleanup_t cu;
pid_t w;
int status;
int error;
- struct sigaction action;
sigset_t mask;
- sigset_t savemask;
struct stat64 buf;
const char *shpath;
- char *argvec[4];
+ char *argv[4];
posix_spawnattr_t attr;
static const char *sun_path = "/bin/sh";
static const char *xpg4_path = "/usr/xpg4/bin/sh";
@@ -120,28 +151,40 @@ system(const char *cmd)
/*
* Initialize the posix_spawn() attributes structure.
+ * The setting of POSIX_SPAWN_WAITPID_NP ensures that no
+ * wait-for-multiple wait() operation will reap our child
+ * and that the child will not be automatically reaped due
+ * to the disposition of SIGCHLD being set to be ignored.
+ * Only a specific wait for the specific pid will be able
+ * to reap the child. Since no other thread knows the pid
+ * of our child, this should be safe enough.
*/
- if ((error = posix_spawnattr_init(&attr)) != 0) {
- errno = error;
- return (-1);
- }
- error = posix_spawnattr_setflags(&attr,
- POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF);
+ error = posix_spawnattr_init(&attr);
+ if (error == 0)
+ error = posix_spawnattr_setflags(&attr,
+ POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF |
+ POSIX_SPAWN_NOSIGCHLD_NP | POSIX_SPAWN_WAITPID_NP);
/*
- * We are required to block SIGCHLD so that we don't cause
- * the process's signal handler, if any, to be called.
- * This doesn't really work for a multithreaded process
- * because some other thread may receive the SIGCHLD.
+ * The POSIX spec for system() requires us to block SIGCHLD,
+ * the rationale being that the process's signal handler for
+ * SIGCHLD, if any, should not be called when our child exits.
+ * This doesn't work for a multithreaded process because some
+ * other thread could receive the SIGCHLD.
+ *
+ * The above setting of POSIX_SPAWN_NOSIGCHLD_NP ensures that no
+ * SIGCHLD signal will be posted for our child when it exits, so
+ * we don't have to block SIGCHLD to meet the intent of the spec.
+ * We block SIGCHLD anyway, just because the spec requires it.
*/
(void) sigemptyset(&mask);
(void) sigaddset(&mask, SIGCHLD);
- (void) sigprocmask(SIG_BLOCK, &mask, &savemask);
+ (void) thr_sigsetmask(SIG_BLOCK, &mask, &cu.savemask);
/*
* Tell posix_spawn() to restore the signal mask in the child.
*/
if (error == 0)
- error = posix_spawnattr_setsigmask(&attr, &savemask);
+ error = posix_spawnattr_setsigmask(&attr, &cu.savemask);
/*
* We are required to set the disposition of SIGINT and SIGQUIT
@@ -158,33 +201,8 @@ system(const char *cmd)
*/
lmutex_lock(&sys_lock);
if (sys_count++ == 0) {
- (void) memset(&action, 0, sizeof (action));
- action.sa_handler = SIG_IGN;
- (void) sigaction(SIGINT, &action, &sys_ibuf);
- (void) sigaction(SIGQUIT, &action, &sys_qbuf);
- /*
- * If the action for SIGCHLD is SIG_IGN, then set it to SIG_DFL
- * so we can retrieve the status of the spawned-off shell.
- * The execve() performed in posix_spawn() will set the action
- * for SIGCHLD in the child process to SIG_DFL regardless,
- * so this has no negative consequencies for the child.
- *
- * Note that this is not required by the SUSv3 standard.
- * The standard permits this error:
- * ECHILD The status of the child process created
- * by system() is no longer available.
- * So we could leave the action for SIGCHLD alone and
- * still be standards-conforming, but this is the way
- * the SunOS system() has always behaved (in fact it
- * used to set the action to SIG_DFL unconditinally),
- * so we retain this behavior here.
- */
- (void) sigaction(SIGCHLD, NULL, &sys_cbuf);
- if (sys_cbuf.sa_handler == SIG_IGN ||
- (sys_cbuf.sa_flags & SA_NOCLDWAIT)) {
- action.sa_handler = SIG_DFL;
- (void) sigaction(SIGCHLD, &action, NULL);
- }
+ (void) sigaction(SIGINT, &ignore, &sys_ibuf);
+ (void) sigaction(SIGQUIT, &ignore, &sys_qbuf);
}
lmutex_unlock(&sys_lock);
@@ -201,13 +219,13 @@ system(const char *cmd)
if (error == 0)
error = posix_spawnattr_setsigdefault(&attr, &mask);
- argvec[0] = (char *)shell;
- argvec[1] = "-c";
- argvec[2] = (char *)cmd;
- argvec[3] = NULL;
+ argv[0] = (char *)shell;
+ argv[1] = "-c";
+ argv[2] = (char *)cmd;
+ argv[3] = NULL;
if (error == 0)
- error = posix_spawn(&pid, shpath, NULL, &attr,
- (char *const *)argvec, (char *const *)environ);
+ error = posix_spawn(&cu.pid, shpath, NULL, &attr,
+ (char *const *)argv, (char *const *)environ);
(void) posix_spawnattr_destroy(&attr);
@@ -220,15 +238,18 @@ system(const char *cmd)
* Call waitpid_cancel() rather than _waitpid() to make
* sure that we actually perform the cancellation logic.
*/
- pthread_cleanup_push(cleanup, &savemask);
+ pthread_cleanup_push(cleanup, &cu);
do {
- w = waitpid_cancel(pid, &status, 0);
+ w = waitpid_cancel(cu.pid, &status, 0);
} while (w == -1 && errno == EINTR);
pthread_cleanup_pop(0);
if (w == -1)
status = -1;
}
- cleanup(&savemask);
+ error = errno;
+ cu.pid = 0;
+ cleanup(&cu);
+ errno = error;
return (status);
}
diff --git a/usr/src/lib/libc/port/threads/scalls.c b/usr/src/lib/libc/port/threads/scalls.c
index 67a2a6341f..e950bb38d1 100644
--- a/usr/src/lib/libc/port/threads/scalls.c
+++ b/usr/src/lib/libc/port/threads/scalls.c
@@ -113,16 +113,10 @@ fork_lock_exit(void)
sigon(self);
}
-/*
- * fork() is fork1() for both Posix threads and Solaris threads.
- * The forkall() interface exists for applications that require
- * the semantics of replicating all threads.
- */
-#pragma weak fork = _fork1
-#pragma weak _fork = _fork1
-#pragma weak fork1 = _fork1
-pid_t
-_fork1(void)
+#pragma weak forkx = _private_forkx
+#pragma weak _forkx = _private_forkx
+static pid_t
+_private_forkx(int flags)
{
ulwp_t *self = curthread;
uberdata_t *udp = self->ul_uberdata;
@@ -140,7 +134,7 @@ _fork1(void)
errno = ENOTSUP;
return (-1);
}
- pid = __fork1();
+ pid = __forkx(flags);
if (pid == 0) { /* child */
udp->pid = _private_getpid();
self->ul_vfork = 0;
@@ -177,7 +171,7 @@ _fork1(void)
* Block all signals.
* Just deferring them via sigon() is not enough.
* We have to avoid taking a deferred signal in the child
- * that was actually sent to the parent before __fork1().
+ * that was actually sent to the parent before __forkx().
*/
block_all_signals(self);
@@ -185,19 +179,19 @@ _fork1(void)
* This suspends all threads but this one, leaving them
* suspended outside of any critical regions in the library.
* Thus, we are assured that no library locks are held
- * while we invoke fork1() from the current thread.
+ * while we invoke fork() from the current thread.
*/
(void) _private_mutex_lock(&udp->fork_lock);
suspend_fork();
(void) _private_mutex_unlock(&udp->fork_lock);
- pid = __fork1();
+ pid = __forkx(flags);
if (pid == 0) { /* child */
/*
* Clear our schedctl pointer.
* Discard any deferred signal that was sent to the parent.
- * Because we blocked all signals before __fork1(), a
+ * Because we blocked all signals before __forkx(), a
* deferred signal cannot have been taken by the child.
*/
self->ul_schedctl_called = NULL;
@@ -210,7 +204,7 @@ _fork1(void)
restore_signals(self);
_postfork_child_handler();
} else {
- /* restart all threads that were suspended for fork1() */
+ /* restart all threads that were suspended for fork() */
continue_fork(0);
restore_signals(self);
_postfork_parent_handler();
@@ -223,12 +217,27 @@ _fork1(void)
}
/*
- * Much of the logic here is the same as in fork1().
- * See the comments in fork1(), above.
+ * fork() is fork1() for both Posix threads and Solaris threads.
+ * The forkall() interface exists for applications that require
+ * the semantics of replicating all threads.
*/
-#pragma weak forkall = _forkall
+#pragma weak fork1 = _fork
+#pragma weak _fork1 = _fork
+#pragma weak fork = _fork
pid_t
-_forkall(void)
+_fork(void)
+{
+ return (_private_forkx(0));
+}
+
+/*
+ * Much of the logic here is the same as in forkx().
+ * See the comments in forkx(), above.
+ */
+#pragma weak forkallx = _private_forkallx
+#pragma weak _forkallx = _private_forkallx
+static pid_t
+_private_forkallx(int flags)
{
ulwp_t *self = curthread;
uberdata_t *udp = self->ul_uberdata;
@@ -240,7 +249,7 @@ _forkall(void)
errno = ENOTSUP;
return (-1);
}
- pid = __forkall();
+ pid = __forkallx(flags);
if (pid == 0) { /* child */
udp->pid = _private_getpid();
self->ul_vfork = 0;
@@ -257,7 +266,7 @@ _forkall(void)
block_all_signals(self);
suspend_fork();
- pid = __forkall();
+ pid = __forkallx(flags);
if (pid == 0) {
self->ul_schedctl_called = NULL;
@@ -276,6 +285,13 @@ _forkall(void)
return (pid);
}
+#pragma weak forkall = _forkall
+pid_t
+_forkall(void)
+{
+ return (_private_forkallx(0));
+}
+
/*
* Hacks for system calls to provide cancellation
* and improve java garbage collection.
diff --git a/usr/src/lib/libc/port/threads/spawn.c b/usr/src/lib/libc/port/threads/spawn.c
index ca3bd3d3d7..ddf74327b5 100644
--- a/usr/src/lib/libc/port/threads/spawn.c
+++ b/usr/src/lib/libc/port/threads/spawn.c
@@ -32,6 +32,7 @@
#include <sys/procset.h>
#include <sys/rtpriocntl.h>
#include <sys/tspriocntl.h>
+#include <sys/fork.h>
#include <sys/rt.h>
#include <sys/ts.h>
#include <alloca.h>
@@ -44,7 +45,9 @@
POSIX_SPAWN_SETSIGDEF | \
POSIX_SPAWN_SETSIGMASK | \
POSIX_SPAWN_SETSCHEDPARAM | \
- POSIX_SPAWN_SETSCHEDULER)
+ POSIX_SPAWN_SETSCHEDULER | \
+ POSIX_SPAWN_NOSIGCHLD_NP | \
+ POSIX_SPAWN_WAITPID_NP)
typedef struct {
short sa_psflags; /* POSIX_SPAWN_* flags */
@@ -69,8 +72,8 @@ typedef struct file_attr {
extern struct pcclass ts_class, rt_class;
-extern pid_t _vfork(void);
-#pragma unknown_control_flow(_vfork)
+extern pid_t _vforkx(int);
+#pragma unknown_control_flow(_vforkx)
extern void *_private_memset(void *, int, size_t);
extern int __lwp_sigmask(int, const sigset_t *, sigset_t *);
extern int __open(const char *, int, mode_t);
@@ -262,6 +265,21 @@ perform_file_actions(file_attr_t *fap)
return (0);
}
+static int
+forkflags(spawn_attr_t *sap)
+{
+ int flags = 0;
+
+ if (sap != NULL) {
+ if (sap->sa_psflags & POSIX_SPAWN_NOSIGCHLD_NP)
+ flags |= FORK_NOSIGCHLD;
+ if (sap->sa_psflags & POSIX_SPAWN_WAITPID_NP)
+ flags |= FORK_WAITPID;
+ }
+
+ return (flags);
+}
+
/*
* set_error() / get_error() are used to guarantee that the local variable
* 'error' is set correctly in memory on return from vfork() in the parent.
@@ -286,7 +304,7 @@ get_error(int *errp)
* (with a defunct owner) and we would deadlock ourself if we invoked it.
*
* Therefore, all of the functions we call here after returning from
- * _vfork() in the child are not and must never be exported from libc
+ * _vforkx() in the child are not and must never be exported from libc
* as global symbols. To do so would risk invoking the dynamic linker.
*/
@@ -308,7 +326,7 @@ _posix_spawn(
if (attrp != NULL && sap == NULL)
return (EINVAL);
- switch (pid = _vfork()) {
+ switch (pid = _vforkx(forkflags(sap))) {
case 0: /* child */
break;
case -1: /* parent, failure */
@@ -410,7 +428,7 @@ _posix_spawnp(
continue;
newargs = alloca((argc + 2) * sizeof (char *));
- switch (pid = _vfork()) {
+ switch (pid = _vforkx(forkflags(sap))) {
case 0: /* child */
break;
case -1: /* parent, failure */
@@ -624,15 +642,11 @@ int
_posix_spawnattr_init(
posix_spawnattr_t *attr)
{
- spawn_attr_t *sap;
-
- if ((sap = lmalloc(sizeof (*sap))) == NULL)
+ if ((attr->__spawn_attrp = lmalloc(sizeof (posix_spawnattr_t))) == NULL)
return (ENOMEM);
-
/*
* Add default stuff here?
*/
- attr->__spawn_attrp = sap;
return (0);
}
diff --git a/usr/src/lib/libc/port/threads/thr.c b/usr/src/lib/libc/port/threads/thr.c
index 483ade8dd7..ac023cf5aa 100644
--- a/usr/src/lib/libc/port/threads/thr.c
+++ b/usr/src/lib/libc/port/threads/thr.c
@@ -1588,7 +1588,7 @@ finish_init()
}
/*
- * Used only by _postfork1_child(), below.
+ * Used only by postfork1_child(), below.
*/
static void
mark_dead_and_buried(ulwp_t *ulwp)
@@ -1745,6 +1745,12 @@ _thr_main()
}
int
+_thrp_cancelled(void)
+{
+ return (curthread->ul_rval == PTHREAD_CANCELED);
+}
+
+int
_thrp_stksegment(ulwp_t *ulwp, stack_t *stk)
{
stk->ss_sp = (void *)ulwp->ul_stktop;
diff --git a/usr/src/lib/libc/sparc/Makefile b/usr/src/lib/libc/sparc/Makefile
index 452b116802..eced13c518 100644
--- a/usr/src/lib/libc/sparc/Makefile
+++ b/usr/src/lib/libc/sparc/Makefile
@@ -330,8 +330,8 @@ SYSOBJS= \
_lwp_mutex_unlock.o \
_stack_grow.o \
door.o \
- fork1.o \
- forkall.o \
+ forkx.o \
+ forkallx.o \
gettimeofday.o \
pipe.o \
ptrace.o \
@@ -341,7 +341,7 @@ SYSOBJS= \
uadmin.o \
umount.o \
uname.o \
- vfork.o
+ vforkx.o
# objects under ../port which contain transitional large file interfaces
PORTGEN64= \
@@ -1214,7 +1214,7 @@ ASSYMDEP_OBJS= \
asm_subr.o \
tls_get_addr.o \
unwind_frame.o \
- vfork.o
+ vforkx.o
$(ASSYMDEP_OBJS:%=pics/%) := CPPFLAGS += -I.
diff --git a/usr/src/lib/libc/sparc/sys/forkall.s b/usr/src/lib/libc/sparc/sys/forkallx.s
index 43ef74e8bb..32dbdadd6e 100644
--- a/usr/src/lib/libc/sparc/sys/forkall.s
+++ b/usr/src/lib/libc/sparc/sys/forkallx.s
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,12 +18,12 @@
*
* CDDL HEADER END
*/
+
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,12 +31,13 @@
.file "%M%"
-/*
- * C library -- forkall
- * pid_t forkall(void)
- */
+#include "SYS.h"
/*
+ * pid = __forkallx(flags);
+ *
+ * syscall trap: forksys(1, flags)
+ *
* From the syscall:
* %o1 == 0 in parent process, %o1 == 1 in child process.
* %o0 == pid of child in parent, %o0 == pid of parent in child.
@@ -46,11 +46,11 @@
* The parent gets the pid of the child.
*/
-#include "SYS.h"
-
- ENTRY(__forkall)
- SYSTRAP_2RVALS(forkall)
+ ENTRY(__forkallx)
+ mov %o0, %o1
+ mov 1, %o0
+ SYSTRAP_2RVALS(forksys)
SYSCERROR
movrnz %o1, 0, %o0
RET
- SET_SIZE(__forkall)
+ SET_SIZE(__forkallx)
diff --git a/usr/src/lib/libc/sparc/sys/fork1.s b/usr/src/lib/libc/sparc/sys/forkx.s
index 1d011cbb37..b86bcbbfcc 100644
--- a/usr/src/lib/libc/sparc/sys/fork1.s
+++ b/usr/src/lib/libc/sparc/sys/forkx.s
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,12 +18,12 @@
*
* CDDL HEADER END
*/
+
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,12 +31,13 @@
.file "%M%"
-/*
- * C library -- fork1
- * pid_t fork1(void)
- */
+#include "SYS.h"
/*
+ * pid = __forkx(flags);
+ *
+ * syscall trap: forksys(0, flags)
+ *
* From the syscall:
* %o1 == 0 in parent process, %o1 == 1 in child process.
* %o0 == pid of child in parent, %o0 == pid of parent in child.
@@ -46,11 +46,11 @@
* The parent gets the pid of the child.
*/
-#include "SYS.h"
-
- ENTRY(__fork1);
- SYSTRAP_2RVALS(fork1);
+ ENTRY(__forkx)
+ mov %o0, %o1
+ clr %o0
+ SYSTRAP_2RVALS(forksys)
SYSCERROR
movrnz %o1, 0, %o0
RET
- SET_SIZE(__fork1)
+ SET_SIZE(__forkx)
diff --git a/usr/src/lib/libc/sparc/sys/vfork.s b/usr/src/lib/libc/sparc/sys/vforkx.s
index 45153a1374..d5e41b571a 100644
--- a/usr/src/lib/libc/sparc/sys/vfork.s
+++ b/usr/src/lib/libc/sparc/sys/vforkx.s
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,66 +18,79 @@
*
* CDDL HEADER END
*/
+
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-.ident "%Z%%M% %I% %E% SMI"
+#pragma ident "%Z%%M% %I% %E% SMI"
-/*
- * C library -- vfork
- * pid_t vfork(void);
- */
+ .file "%M%"
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(vforkx,function)
+ ANSI_PRAGMA_WEAK(vfork,function)
+
+#include "SYS.h"
+#include <assym.h>
/*
+ * pid = vforkx(flags);
+ * syscall trap: forksys(2, flags)
+ *
+ * pid = vfork();
+ * syscall trap: forksys(2, 0)
+ *
* From the syscall:
* %o1 == 0 in parent process, %o1 == 1 in child process.
* %o0 == pid of child in parent, %o0 == pid of parent in child.
*
- * The child process gets a zero return value from vfork; the parent
- * gets the pid of the child.
+ * The child gets a zero return value.
+ * The parent gets the pid of the child.
+ */
+
+/*
+ * Note that since the SPARC architecture maintains stack maintence
+ * information (return pc, sp, fp) in the register windows, both parent
+ * and child can execute in a common address space without conflict.
*
* We block all blockable signals while performing the vfork() system call
* trap. This enables us to set curthread->ul_vfork safely, so that we
* don't end up in a signal handler with curthread->ul_vfork set wrong.
- *
- * Note that since the SPARC architecture maintains stack maintence
- * information (return pc, sp, fp) in the register windows, both parent
- * and child can execute in a common address space without conflict.
*/
- .file "%M%"
-
-#include <sys/asm_linkage.h>
-
- ANSI_PRAGMA_WEAK(vfork,function)
-
-#include "SYS.h"
-#include <../assym.h>
-
- ENTRY(vfork)
- mov SIG_SETMASK, %o0 ! block signals
+ ENTRY_NP(vforkx)
+ ba 0f
+ mov %o0, %o3 /* flags */
+ ENTRY_NP(vfork)
+ clr %o3 /* flags = 0 */
+0:
+ mov SIG_SETMASK, %o0 /* block all signals */
set MASKSET0, %o1
set MASKSET1, %o2
SYSTRAP_2RVALS(lwp_sigmask)
- SYSTRAP_2RVALS(vfork)
+ mov %o3, %o1 /* flags */
+ mov 2, %o0
+ SYSTRAP_2RVALS(forksys) /* vforkx(flags) */
bcc,a,pt %icc, 1f
tst %o1
- mov %o0, %o3 ! save the vfork() error number
- mov SIG_SETMASK, %o0 ! reinstate signals
+ mov %o0, %o3 /* save the vfork() error number */
+
+ mov SIG_SETMASK, %o0 /* reinstate signals */
ld [%g7 + UL_SIGMASK], %o1
ld [%g7 + UL_SIGMASK + 4], %o2
SYSTRAP_2RVALS(lwp_sigmask)
- mov %o3, %o0 ! restore the vfork() error number
- ba,a __cerror
+ ba __cerror
+ mov %o3, %o0 /* restore the vfork() error number */
+
1:
/*
* To determine if we are (still) a child of vfork(), the child
@@ -89,12 +101,12 @@
*/
bnz,pt %icc, 2f
ld [%g7 + UL_VFORK], %g1
- brnz,a,pt %g1, 3f ! don't let it go negative
- sub %g1, 1, %g1 ! curthread->ul_vfork--;
+ brnz,a,pt %g1, 3f /* don't let it go negative */
+ sub %g1, 1, %g1 /* curthread->ul_vfork--; */
ba,a 3f
2:
- clr %o0 ! child, return (0)
- add %g1, 1, %g1 ! curthread->ul_vfork++;
+ clr %o0 /* zero the return value in the child */
+ add %g1, 1, %g1 /* curthread->ul_vfork++; */
3:
st %g1, [%g7 + UL_VFORK]
/*
@@ -103,13 +115,14 @@
*/
stn %g0, [%g7 + UL_SCHEDCTL]
stn %g0, [%g7 + UL_SCHEDCTL_CALLED]
- mov %o0, %o3 ! save the vfork() return value
+ mov %o0, %o3 /* save the vfork() return value */
- mov SIG_SETMASK, %o0 ! reinstate signals
+ mov SIG_SETMASK, %o0 /* reinstate signals */
ld [%g7 + UL_SIGMASK], %o1
ld [%g7 + UL_SIGMASK + 4], %o2
SYSTRAP_2RVALS(lwp_sigmask)
retl
- mov %o3, %o0 ! restore the vfork() return value
+ mov %o3, %o0 /* restore the vfork() return value */
SET_SIZE(vfork)
+ SET_SIZE(vforkx)
diff --git a/usr/src/lib/libc/sparcv9/Makefile b/usr/src/lib/libc/sparcv9/Makefile
index bfbb37f2d8..04054aaa81 100644
--- a/usr/src/lib/libc/sparcv9/Makefile
+++ b/usr/src/lib/libc/sparcv9/Makefile
@@ -316,8 +316,8 @@ SYSOBJS= \
_lwp_mutex_unlock.o \
_stack_grow.o \
door.o \
- fork1.o \
- forkall.o \
+ forkx.o \
+ forkallx.o \
gettimeofday.o \
pipe.o \
sparc_utrap_install.o \
@@ -327,7 +327,7 @@ SYSOBJS= \
uadmin.o \
umount.o \
uname.o \
- vfork.o
+ vforkx.o
# Preserved solely to ease maintenance of 32-bit and 64-bit library builds
# This macro should ALWAYS be empty; native APIs are already 'large file'.
@@ -1150,7 +1150,7 @@ ASSYMDEP_OBJS= \
asm_subr.o \
tls_get_addr.o \
unwind_frame.o \
- vfork.o
+ vforkx.o
$(ASSYMDEP_OBJS:%=pics/%) := CPPFLAGS += -I.
diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c
index 5a9321b178..db7a384b18 100644
--- a/usr/src/lib/libdtrace/common/dt_open.c
+++ b/usr/src/lib/libdtrace/common/dt_open.c
@@ -99,8 +99,9 @@
#define DT_VERS_1_2_1 DT_VERSION_NUMBER(1, 2, 1)
#define DT_VERS_1_2_2 DT_VERSION_NUMBER(1, 2, 2)
#define DT_VERS_1_3 DT_VERSION_NUMBER(1, 3, 0)
-#define DT_VERS_LATEST DT_VERS_1_3
-#define DT_VERS_STRING "Sun D 1.3"
+#define DT_VERS_1_4 DT_VERSION_NUMBER(1, 4, 0)
+#define DT_VERS_LATEST DT_VERS_1_4
+#define DT_VERS_STRING "Sun D 1.4"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -109,6 +110,7 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_2_1, /* D API 1.2.1 Solaris Express 4/06 */
DT_VERS_1_2_2, /* D API 1.2.2 Solaris Express 6/06 */
DT_VERS_1_3, /* D API 1.3 Solaris Express 10/06 */
+ DT_VERS_1_4, /* D API 1.4 Solaris Express 2/07 */
0
};
diff --git a/usr/src/lib/libdtrace/common/dt_proc.c b/usr/src/lib/libdtrace/common/dt_proc.c
index 66bc3aa011..3d739a7b06 100644
--- a/usr/src/lib/libdtrace/common/dt_proc.c
+++ b/usr/src/lib/libdtrace/common/dt_proc.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -91,7 +90,8 @@
#include <dt_impl.h>
#define IS_SYS_EXEC(w) (w == SYS_exec || w == SYS_execve)
-#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_fork1 || w == SYS_forkall)
+#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_fork1 || \
+ w == SYS_forkall || w == SYS_forksys)
static dt_bkpt_t *
dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data)
@@ -504,6 +504,8 @@ dt_proc_control(void *arg)
(void) Psysexit(P, SYS_fork1, B_TRUE);
(void) Psysentry(P, SYS_forkall, B_TRUE);
(void) Psysexit(P, SYS_forkall, B_TRUE);
+ (void) Psysentry(P, SYS_forksys, B_TRUE);
+ (void) Psysexit(P, SYS_forksys, B_TRUE);
Psync(P); /* enable all /proc changes */
dt_proc_attach(dpr, B_FALSE); /* enable rtld breakpoints */
diff --git a/usr/src/lib/libdtrace/common/procfs.d.in b/usr/src/lib/libdtrace/common/procfs.d.in
index 5d97197c31..915d754d88 100644
--- a/usr/src/lib/libdtrace/common/procfs.d.in
+++ b/usr/src/lib/libdtrace/common/procfs.d.in
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -69,12 +70,18 @@ inline int PR_DETACH = @PR_DETACH@;
#pragma D binding "1.0" PR_DETACH
inline int PR_DAEMON = @PR_DAEMON@;
#pragma D binding "1.0" PR_DAEMON
+inline int PR_IDLE = @PR_IDLE@;
+#pragma D binding "1.4" PR_IDLE
inline int PR_ISSYS = @PR_ISSYS@;
#pragma D binding "1.0" PR_ISSYS
inline int PR_VFORKP = @PR_VFORKP@;
#pragma D binding "1.0" PR_VFORKP
inline int PR_ORPHAN = @PR_ORPHAN@;
#pragma D binding "1.0" PR_ORPHAN
+inline int PR_NOSIGCHLD = @PR_NOSIGCHLD@;
+#pragma D binding "1.4" PR_NOSIGCHLD
+inline int PR_WAITPID = @PR_WAITPID@;
+#pragma D binding "1.4" PR_WAITPID
inline int PR_FORK = @PR_FORK@;
#pragma D binding "1.0" PR_FORK
inline int PR_RLC = @PR_RLC@;
@@ -91,8 +98,6 @@ inline int PR_PTRACE = @PR_PTRACE@;
#pragma D binding "1.0" PR_PTRACE
inline int PR_MSFORK = @PR_MSFORK@;
#pragma D binding "1.0" PR_MSFORK
-inline int PR_IDLE = @PR_IDLE@;
-#pragma D binding "1.0" PR_IDLE
inline char PR_MODEL_ILP32 = @PR_MODEL_ILP32@;
#pragma D binding "1.0" PR_MODEL_ILP32
@@ -292,6 +297,8 @@ translator lwpsinfo_t < kthread_t *T > {
((T == T->t_procp->p_agenttp) ? PR_AGENT : 0) |
((!(T->t_proc_flag & @TP_TWAIT@)) ? PR_DETACH : 0) |
((T->t_proc_flag & @TP_DAEMON@) ? PR_DAEMON : 0) |
+ ((T->t_procp->p_pidflag & @CLDNOSIGCHLD@) ? PR_NOSIGCHLD : 0) |
+ ((T->t_procp->p_pidflag & @CLDWAITPID@) ? PR_WAITPID : 0) |
((T->t_procp->p_proc_flag & @P_PR_FORK@) ? PR_FORK : 0) |
((T->t_procp->p_proc_flag & @P_PR_RUNLCL@) ? PR_RLC : 0) |
((T->t_procp->p_proc_flag & @P_PR_KILLCL@) ? PR_KLC : 0) |
diff --git a/usr/src/lib/libdtrace/common/procfs.sed.in b/usr/src/lib/libdtrace/common/procfs.sed.in
index a3d7a23f08..f889f6333c 100644
--- a/usr/src/lib/libdtrace/common/procfs.sed.in
+++ b/usr/src/lib/libdtrace/common/procfs.sed.in
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -76,6 +76,9 @@ SED_REPLACE(SSTOP)
SED_REPLACE(SIDL)
SED_REPLACE(SONPROC)
+SED_REPLACE(CLDNOSIGCHLD)
+SED_REPLACE(CLDWAITPID)
+
SED_REPLACE(PR_STOPPED)
SED_REPLACE(PR_ISTOP)
SED_REPLACE(PR_DSTOP)
@@ -86,9 +89,12 @@ SED_REPLACE(PR_ASLWP)
SED_REPLACE(PR_AGENT)
SED_REPLACE(PR_DETACH)
SED_REPLACE(PR_DAEMON)
+SED_REPLACE(PR_IDLE)
SED_REPLACE(PR_ISSYS)
SED_REPLACE(PR_VFORKP)
SED_REPLACE(PR_ORPHAN)
+SED_REPLACE(PR_NOSIGCHLD)
+SED_REPLACE(PR_WAITPID)
SED_REPLACE(PR_FORK)
SED_REPLACE(PR_RLC)
SED_REPLACE(PR_KLC)
@@ -97,7 +103,6 @@ SED_REPLACE(PR_MSACCT)
SED_REPLACE(PR_BPTADJ)
SED_REPLACE(PR_PTRACE)
SED_REPLACE(PR_MSFORK)
-SED_REPLACE(PR_IDLE)
SED_REPLACE(PR_MODEL_ILP32)
SED_REPLACE(PR_MODEL_LP64)
diff --git a/usr/src/lib/libpctx/common/libpctx.c b/usr/src/lib/libpctx/common/libpctx.c
index 83f5f91fde..9c28fb9b9b 100644
--- a/usr/src/lib/libpctx/common/libpctx.c
+++ b/usr/src/lib/libpctx/common/libpctx.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -318,12 +319,14 @@ pctx_set_events(pctx_t *pctx, ...)
(void) Psysexit(pctx->Pr, SYS_forkall, 1);
(void) Psysexit(pctx->Pr, SYS_vfork, 1);
(void) Psysexit(pctx->Pr, SYS_fork1, 1);
+ (void) Psysexit(pctx->Pr, SYS_forksys, 1);
if (Psetflags(pctx->Pr, PR_FORK) == -1)
error = -1;
} else {
(void) Psysexit(pctx->Pr, SYS_forkall, 0);
(void) Psysexit(pctx->Pr, SYS_vfork, 0);
(void) Psysexit(pctx->Pr, SYS_fork1, 0);
+ (void) Psysexit(pctx->Pr, SYS_forksys, 0);
if (Punsetflags(pctx->Pr, PR_FORK) == -1)
error = -1;
}
@@ -758,6 +761,7 @@ checkstate:
case SYS_forkall:
case SYS_vfork:
case SYS_fork1:
+ case SYS_forksys:
if (pstatus->pr_lwp.pr_errno)
break;
(void) fflush(NULL);
diff --git a/usr/src/lib/libtnfctl/continue.c b/usr/src/lib/libtnfctl/continue.c
index ee2d3840d9..ab9f5d5701 100644
--- a/usr/src/lib/libtnfctl/continue.c
+++ b/usr/src/lib/libtnfctl/continue.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 1994,2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -253,6 +253,7 @@ again:
case SYS_forkall:
case SYS_vfork:
case SYS_fork1:
+ case SYS_forksys:
*evt = TNFCTL_EVENT_FORK;
break;
default:
@@ -306,6 +307,11 @@ enable_target_state(tnfctl_handle_t *hndl, boolean_t watch_forks)
prbstat = prb_proc_exit(proc_p, SYS_fork1, PRB_SYS_ADD);
if (prbstat)
return (_tnfctl_map_to_errcode(prbstat));
+
+ prbstat = prb_proc_exit(proc_p, SYS_forksys, PRB_SYS_ADD);
+ if (prbstat)
+ return (_tnfctl_map_to_errcode(prbstat));
+
prbstat = prb_proc_setfork(proc_p, B_TRUE);
if (prbstat)
return (_tnfctl_map_to_errcode(prbstat));
@@ -355,6 +361,9 @@ disable_target_state(tnfctl_handle_t *hndl)
prbstat = prb_proc_exit(proc_p, SYS_fork1, PRB_SYS_DEL);
if (prbstat)
return (_tnfctl_map_to_errcode(prbstat));
+ prbstat = prb_proc_exit(proc_p, SYS_forksys, PRB_SYS_DEL);
+ if (prbstat)
+ return (_tnfctl_map_to_errcode(prbstat));
prbstat = prb_proc_setfork(proc_p, B_FALSE);
if (prbstat)
return (_tnfctl_map_to_errcode(prbstat));
diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com
index 20f6f0e581..c52316079d 100644
--- a/usr/src/pkgdefs/SUNWhea/prototype_com
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com
@@ -683,6 +683,7 @@ f none usr/include/sys/fm/io/ddi.h 644 root bin
f none usr/include/sys/fm/io/opl_mc_fm.h 644 root bin
f none usr/include/sys/fm/io/pci.h 644 root bin
f none usr/include/sys/fm/io/sun4upci.h 644 root bin
+f none usr/include/sys/fork.h 644 root bin
f none usr/include/sys/frame.h 644 root bin
f none usr/include/sys/fss.h 644 root bin
f none usr/include/sys/fsspriocntl.h 644 root bin
diff --git a/usr/src/ucbcmd/sbcp/syscalls.list b/usr/src/ucbcmd/sbcp/syscalls.list
index 8a53d3487c..cb11850df6 100644
--- a/usr/src/ucbcmd/sbcp/syscalls.list
+++ b/usr/src/ucbcmd/sbcp/syscalls.list
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -19,14 +18,14 @@
#
# CDDL HEADER END
#
-# Copyright 2000 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
nosys NOSYS /* 0 = 1, indir */
exit TRAP /* 1 = 1, exit */
-fork TRAP /* 2 = 0, fork */
+forkall TRAP /* 2 = 0, fork */
read SIMPLE /* 3 = 3, read */
write SIMPLE /* 4 = 3, write */
open SIMPLE /* 5 = 3, open */
diff --git a/usr/src/uts/common/c2/audit_event.c b/usr/src/uts/common/c2/audit_event.c
index b45da7bf26..696e464765 100644
--- a/usr/src/uts/common/c2/audit_event.c
+++ b/usr/src/uts/common/c2/audit_event.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -96,6 +97,7 @@ static au_event_t aui_modctl(au_event_t);
static au_event_t aui_acl(au_event_t);
static au_event_t aui_doorfs(au_event_t);
static au_event_t aui_privsys(au_event_t);
+static au_event_t aui_forksys(au_event_t);
static void aus_null(struct t_audit_data *);
static void aus_open(struct t_audit_data *);
@@ -492,7 +494,7 @@ aui_null, AUE_NULL, aus_null, /* 140 reserved */
auf_null, 0,
aui_null, AUE_SETEUID, aus_seteuid, /* 141 seteuid */
auf_null, 0,
-aui_null, AUE_NULL, aus_null, /* 142 (loadable reserved) */
+aui_forksys, AUE_NULL, aus_null, /* 142 forksys */
auf_null, 0,
aui_null, AUE_FORK1, aus_null, /* 143 fork1 */
auf_null, 0,
@@ -5577,3 +5579,29 @@ auf_send(tad, error, rval)
au_uwrite(au_to_socket_ex(so_family, so_type, so_laddr, so_faddr));
}
+
+static au_event_t
+aui_forksys(au_event_t e)
+{
+ struct a {
+ long subcode;
+ long flags;
+ } *uap = (struct a *)ttolwp(curthread)->lwp_ap;
+
+ switch ((uint_t)uap->subcode) {
+ case 0:
+ e = AUE_FORK1;
+ break;
+ case 1:
+ e = AUE_FORKALL;
+ break;
+ case 2:
+ e = AUE_VFORK;
+ break;
+ default:
+ e = AUE_NULL;
+ break;
+ }
+
+ return (e);
+}
diff --git a/usr/src/uts/common/fs/proc/prsubr.c b/usr/src/uts/common/fs/proc/prsubr.c
index 619666e5a8..e1c33384f7 100644
--- a/usr/src/uts/common/fs/proc/prsubr.c
+++ b/usr/src/uts/common/fs/proc/prsubr.c
@@ -27,7 +27,6 @@
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
@@ -1192,6 +1191,10 @@ prgetlwpstatus(kthread_t *t, lwpstatus_t *sp, zone_t *zp)
flags |= PR_VFORKP;
if (p->p_pgidp->pid_pgorphaned)
flags |= PR_ORPHAN;
+ if (p->p_pidflag & CLDNOSIGCHLD)
+ flags |= PR_NOSIGCHLD;
+ if (p->p_pidflag & CLDWAITPID)
+ flags |= PR_WAITPID;
sp->pr_flags = flags;
if (VSTOPPED(t)) {
sp->pr_why = PR_REQUESTED;
diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c
index 08cf840697..5ceafd48af 100644
--- a/usr/src/uts/common/os/exit.c
+++ b/usr/src/uts/common/os/exit.c
@@ -643,6 +643,7 @@ proc_exit(int why, int what)
delete_ns(q->p_parent, q);
q->p_ppid = 1;
+ q->p_pidflag &= ~(CLDNOSIGCHLD | CLDWAITPID);
if (setzonetop) {
mutex_enter(&q->p_lock);
q->p_flag |= SZONETOP;
@@ -783,9 +784,10 @@ proc_exit(int why, int what)
t->t_procp = &p0;
mutex_exit(&p->p_lock);
- if (!evaporate)
+ if (!evaporate) {
+ p->p_pidflag &= ~CLDPEND;
sigcld(p, sqp);
- else {
+ } else {
/*
* Do what sigcld() would do if the disposition
* of the SIGCHLD signal were set to be ignored.
@@ -853,7 +855,6 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
{
int found;
proc_t *cp, *pp;
- proc_t **nsp;
int proc_gone;
int waitflag = !(options & WNOWAIT);
@@ -892,9 +893,8 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
* is empty no reason to look at all children.
*/
if (idtype == P_ALL &&
- (options & (WOPTMASK & ~WNOWAIT)) == (WNOHANG | WEXITED) &&
+ (options & ~WNOWAIT) == (WNOHANG | WEXITED) &&
pp->p_child_ns == NULL) {
-
if (pp->p_child) {
mutex_exit(&pidlock);
bzero(ip, sizeof (k_siginfo_t));
@@ -904,26 +904,26 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
return (ECHILD);
}
- while ((cp = pp->p_child) != NULL) {
+ while (pp->p_child != NULL) {
proc_gone = 0;
- for (nsp = &pp->p_child_ns; *nsp; nsp = &(*nsp)->p_sibling_ns) {
- if (idtype == P_PID && id != (*nsp)->p_pid) {
+ for (cp = pp->p_child_ns; cp != NULL; cp = cp->p_sibling_ns) {
+ if (idtype != P_PID && (cp->p_pidflag & CLDWAITPID))
continue;
- }
- if (idtype == P_PGID && id != (*nsp)->p_pgrp) {
+ if (idtype == P_PID && id != cp->p_pid)
+ continue;
+ if (idtype == P_PGID && id != cp->p_pgrp)
continue;
- }
- switch ((*nsp)->p_wcode) {
+ switch (cp->p_wcode) {
case CLD_TRAPPED:
case CLD_STOPPED:
case CLD_CONTINUED:
cmn_err(CE_PANIC,
"waitid: wrong state %d on the p_newstate"
- " list", (*nsp)->p_wcode);
+ " list", cp->p_wcode);
break;
case CLD_EXITED:
@@ -938,11 +938,10 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
break;
}
if (!waitflag) {
- winfo((*nsp), ip, 0);
+ winfo(cp, ip, 0);
} else {
- proc_t *xp = *nsp;
- winfo(xp, ip, 1);
- freeproc(xp);
+ winfo(cp, ip, 1);
+ freeproc(cp);
}
mutex_exit(&pidlock);
if (waitflag) { /* accept SIGCLD */
@@ -961,16 +960,11 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
* interesting threads. Check all the kids!
*/
found = 0;
- cp = pp->p_child;
- do {
- if (idtype == P_PID && id != cp->p_pid) {
+ for (cp = pp->p_child; cp != NULL; cp = cp->p_sibling) {
+ if (idtype == P_PID && id != cp->p_pid)
continue;
- }
- if (idtype == P_PGID && id != cp->p_pgrp) {
+ if (idtype == P_PGID && id != cp->p_pgrp)
continue;
- }
-
- found++;
switch (cp->p_wcode) {
case CLD_TRAPPED:
@@ -1016,6 +1010,9 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
case CLD_EXITED:
case CLD_DUMPED:
case CLD_KILLED:
+ if (idtype != P_PID &&
+ (cp->p_pidflag & CLDWAITPID))
+ continue;
/*
* Don't complain if a process was found in
* the first loop but we broke out of the loop
@@ -1030,9 +1027,11 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
}
}
+ found++;
+
if (idtype == P_PID)
break;
- } while ((cp = cp->p_sibling) != NULL);
+ }
/*
* If we found no interesting processes at all,
@@ -1042,13 +1041,13 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
break;
if (options & WNOHANG) {
+ mutex_exit(&pidlock);
bzero(ip, sizeof (k_siginfo_t));
/*
* We should set ip->si_signo = SIGCLD,
* but there is an SVVS test that expects
* ip->si_signo to be zero in this case.
*/
- mutex_exit(&pidlock);
return (0);
}
@@ -1070,9 +1069,9 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
}
/*
- * For implementations that don't require binary compatibility,
- * the wait system call may be made into a library call to the
- * waitid system call.
+ * The wait() system call trap is no longer invoked by libc.
+ * It is retained only for the benefit of statically linked applications.
+ * Delete this when we no longer care about these old and broken applications.
*/
int64_t
wait(void)
diff --git a/usr/src/uts/common/os/fork.c b/usr/src/uts/common/os/fork.c
index b2d1e69cc9..177c28316b 100644
--- a/usr/src/uts/common/os/fork.c
+++ b/usr/src/uts/common/os/fork.c
@@ -27,7 +27,6 @@
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
@@ -81,8 +80,9 @@
#include <sys/class.h>
#include <sys/corectl.h>
#include <sys/brand.h>
+#include <sys/fork.h>
-static int64_t cfork(int, int);
+static int64_t cfork(int, int, int);
static int getproc(proc_t **, int);
static void fork_fail(proc_t *);
static void forklwp_fail(proc_t *);
@@ -97,7 +97,7 @@ extern struct kmem_cache *process_cache;
int64_t
forkall(void)
{
- return (cfork(0, 0));
+ return (cfork(0, 0, 0));
}
/*
@@ -107,21 +107,48 @@ int64_t
vfork(void)
{
curthread->t_post_sys = 1; /* so vfwait() will be called */
- return (cfork(1, 1));
+ return (cfork(1, 1, 0));
}
/*
- * fork1 system call
+ * fork system call, aka fork1.
*/
int64_t
fork1(void)
{
- return (cfork(0, 1));
+ return (cfork(0, 1, 0));
+}
+
+/*
+ * The forkall(), vfork(), and fork1() system calls are no longer
+ * invoked by libc. They are retained only for the benefit of
+ * old statically-linked applications. They should be eliminated
+ * when we no longer care about such old and broken applications.
+ */
+
+/*
+ * forksys system call - forkx, forkallx, vforkx.
+ * This is the interface now invoked by libc.
+ */
+int64_t
+forksys(int subcode, int flags)
+{
+ switch (subcode) {
+ case 0:
+ return (cfork(0, 1, flags)); /* forkx(flags) */
+ case 1:
+ return (cfork(0, 0, flags)); /* forkallx(flags) */
+ case 2:
+ curthread->t_post_sys = 1; /* so vfwait() will be called */
+ return (cfork(1, 1, flags)); /* vforkx(flags) */
+ default:
+ return ((int64_t)set_errno(EINVAL));
+ }
}
/* ARGSUSED */
static int64_t
-cfork(int isvfork, int isfork1)
+cfork(int isvfork, int isfork1, int flags)
{
proc_t *p = ttoproc(curthread);
struct as *as;
@@ -140,6 +167,14 @@ cfork(int isvfork, int isfork1)
lwpent_t *clep;
/*
+ * Allow only these two flags.
+ */
+ if ((flags & ~(FORK_NOSIGCHLD | FORK_WAITPID)) != 0) {
+ error = EINVAL;
+ goto forkerr;
+ }
+
+ /*
* fork is not supported for the /proc agent lwp.
*/
if (curthread == p->p_agenttp) {
@@ -487,6 +522,14 @@ cfork(int isvfork, int isfork1)
mutex_enter(&cp->p_lock);
/*
+ * Set flags telling the child what (not) to do on exit.
+ */
+ if (flags & FORK_NOSIGCHLD)
+ cp->p_pidflag |= CLDNOSIGCHLD;
+ if (flags & FORK_WAITPID)
+ cp->p_pidflag |= CLDWAITPID;
+
+ /*
* Now that there are lwps and threads attached, add the new
* process to the process group.
*/
@@ -517,7 +560,7 @@ cfork(int isvfork, int isfork1)
if (isvfork) {
CPU_STATS_ADDQ(CPU, sys, sysvfork, 1);
mutex_enter(&p->p_lock);
- p->p_flag |= SVFWAIT;
+ p->p_flag |= (SVFPARENT | SVFWAIT);
DTRACE_PROC1(create, proc_t *, cp);
cv_broadcast(&pr_pid_cv[p->p_slot]); /* inform /proc */
mutex_exit(&p->p_lock);
@@ -1309,6 +1352,7 @@ vfwait(pid_t pid)
mutex_enter(&pp->p_lock);
prbarrier(pp); /* barrier against /proc locking */
+ pp->p_flag &= ~SVFPARENT;
continuelwps(pp);
mutex_exit(&pp->p_lock);
}
diff --git a/usr/src/uts/common/os/sig.c b/usr/src/uts/common/os/sig.c
index 872039c362..8d46a3405f 100644
--- a/usr/src/uts/common/os/sig.c
+++ b/usr/src/uts/common/os/sig.c
@@ -1600,14 +1600,15 @@ setsigact(int sig, void (*disp)(), k_sigset_t mask, int flags)
else
p->p_flag |= SJCTL;
- if (p->p_flag & SNOWAIT || disp == SIG_IGN) {
+ if ((p->p_flag & SNOWAIT) || disp == SIG_IGN) {
proc_t *cp, *tp;
mutex_exit(&p->p_lock);
mutex_enter(&pidlock);
for (cp = p->p_child; cp != NULL; cp = tp) {
tp = cp->p_sibling;
- if (cp->p_stat == SZOMB)
+ if (cp->p_stat == SZOMB &&
+ !(cp->p_pidflag & CLDWAITPID))
freeproc(cp);
}
mutex_exit(&pidlock);
@@ -1679,9 +1680,10 @@ sigcld(proc_t *cp, sigqueue_t *sqp)
cv_broadcast(&pp->p_cv);
if ((pp->p_flag & SNOWAIT) ||
- (PTOU(pp)->u_signal[SIGCLD - 1] == SIG_IGN))
- freeproc(cp);
- else {
+ PTOU(pp)->u_signal[SIGCLD - 1] == SIG_IGN) {
+ if (!(cp->p_pidflag & CLDWAITPID))
+ freeproc(cp);
+ } else if (!(cp->p_pidflag & CLDNOSIGCHLD)) {
post_sigcld(cp, sqp);
sqp = NULL;
}
diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c
index 93fb6a0d75..9ada0aac18 100644
--- a/usr/src/uts/common/os/sysent.c
+++ b/usr/src/uts/common/os/sysent.c
@@ -65,6 +65,8 @@ int exec();
int exece();
int fcntl();
int64_t forkall();
+int64_t vfork();
+int64_t forksys();
int64_t fork1();
int fstat();
int fsat32();
@@ -179,7 +181,6 @@ caddr_t smmap32();
int smmaplf32();
int mprotect();
int munmap();
-int64_t vfork();
#if (defined(__i386) && !defined(__amd64)) || defined(__i386_COMPAT)
int xstat();
int lxstat();
@@ -478,14 +479,14 @@ struct sysent sysent[NSYSCALL] =
/* 39 */ SYSENT_CI("setpgrp", setpgrp, 3),
/* 40 */ SYSENT_CI("uucopystr", uucopystr, 3),
/* 41 */ SYSENT_CI("dup", dup, 1),
- /* 42 */ SYSENT_LOADABLE(), /* (was pipe ) */
+ /* 42 */ SYSENT_LOADABLE(), /* pipe */
/* 43 */ SYSENT_CL("times", times, 1),
/* 44 */ SYSENT_CI("prof", profil, 4),
/* 45 */ SYSENT_LOADABLE(), /* (was proc lock) */
/* 46 */ SYSENT_CI("setgid", setgid, 1),
/* 47 */ SYSENT_2CI("getgid", getgid, 0),
/* 48 */ SYSENT_CI("sig", ssig, 2),
- /* 49 */ SYSENT_LOADABLE(), /* (was msgsys) */
+ /* 49 */ SYSENT_LOADABLE(), /* msgsys */
/* 50 */ IF_x86(
SYSENT_CI("sysi86", sysi86, 4),
SYSENT_LOADABLE()), /* (was sys3b) */
@@ -618,7 +619,7 @@ struct sysent sysent[NSYSCALL] =
/* 139 */ SYSENT_CL("systeminfo", systeminfo, 3),
/* 140 */ SYSENT_LOADABLE(), /* reserved */
/* 141 */ SYSENT_CI("seteuid", seteuid, 1),
- /* 142 */ SYSENT_LOADABLE(), /* reserved */
+ /* 142 */ SYSENT_2CI("forksys", forksys, 2),
/* 143 */ SYSENT_2CI("fork1", fork1, 0),
/* 144 */ SYSENT_CI("sigtimedwait", sigtimedwait, 3),
/* 145 */ SYSENT_CI("lwp_info", lwp_info, 1),
@@ -881,14 +882,14 @@ struct sysent sysent32[NSYSCALL] =
/* 39 */ SYSENT_CI("setpgrp", setpgrp, 3),
/* 40 */ SYSENT_CI("uucopystr", uucopystr, 3),
/* 41 */ SYSENT_CI("dup", dup, 1),
- /* 42 */ SYSENT_LOADABLE32(), /* (was pipe ) */
+ /* 42 */ SYSENT_LOADABLE32(), /* pipe */
/* 43 */ SYSENT_CI("times", times32, 1),
/* 44 */ SYSENT_CI("prof", profil, 4),
/* 45 */ SYSENT_LOADABLE32(), /* (was proc lock) */
/* 46 */ SYSENT_CI("setgid", setgid, 1),
/* 47 */ SYSENT_2CI("getgid", getgid, 0),
/* 48 */ SYSENT_CI("sig", ssig, 2),
- /* 49 */ SYSENT_LOADABLE32(), /* (was msgsys) */
+ /* 49 */ SYSENT_LOADABLE32(), /* msgsys */
/* 50 */ IF_386_ABI(
SYSENT_CI("sysi86", sysi86, 4),
SYSENT_LOADABLE()), /* (was sys3b) */
@@ -1002,7 +1003,7 @@ struct sysent sysent32[NSYSCALL] =
/* 139 */ SYSENT_CI("systeminfo", systeminfo, 3),
/* 140 */ SYSENT_LOADABLE32(), /* reserved */
/* 141 */ SYSENT_CI("seteuid", seteuid, 1),
- /* 142 */ SYSENT_LOADABLE32(), /* reserved */
+ /* 142 */ SYSENT_2CI("forksys", forksys, 2),
/* 143 */ SYSENT_2CI("fork1", fork1, 0),
/* 144 */ SYSENT_CI("sigtimedwait", sigtimedwait, 3),
/* 145 */ SYSENT_CI("lwp_info", lwp_info, 1),
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index 9c96c9e4b7..ab103ef4c7 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -233,6 +233,7 @@ CHKHDRS= \
filio.h \
flock.h \
flock_impl.h \
+ fork.h \
fss.h \
fsspriocntl.h \
fsid.h \
diff --git a/usr/src/uts/common/sys/fork.h b/usr/src/uts/common/sys/fork.h
new file mode 100644
index 0000000000..2952bc505d
--- /dev/null
+++ b/usr/src/uts/common/sys/fork.h
@@ -0,0 +1,83 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_FORK_H
+#define _SYS_FORK_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__)
+
+#if !defined(_KERNEL)
+
+extern pid_t forkx(int);
+extern pid_t forkallx(int);
+extern pid_t vforkx(int);
+
+#if defined(__sparc)
+#pragma unknown_control_flow(vforkx)
+#endif
+
+#endif /* !defined(_KERNEL) */
+
+/*
+ * The argument to any of the forkx() functions is a set of flags
+ * formed by or-ing together zero or more of the following flags.
+ * fork()/forkall()/vfork() are equivalent to the corresponding
+ * forkx()/forkallx()/vforkx() functions with a zero argument.
+ */
+
+/*
+ * Do not post a SIGCHLD signal to the parent when the child terminates,
+ * regardless of the disposition of the SIGCHLD signal in the parent.
+ * SIGCHLD signals are still possible for job control stop and continue
+ * actions (CLD_STOPPED, CLD_CONTINUED) if the parent has requested them.
+ */
+#define FORK_NOSIGCHLD 0x0001
+
+/*
+ * Do not allow wait-for-multiple-pids by the parent, as in waitid(P_ALL)
+ * or waitid(P_PGID), to reap the child and do not allow the child to
+ * be reaped automatically due the disposition of the SIGCHLD signal
+ * being set to be ignored. Only a specific wait for the child, as
+ * in waitid(P_PID, pid), is allowed and it is required, else when
+ * the child exits it will remain a zombie until the parent exits.
+ */
+#define FORK_WAITPID 0x0002
+
+#endif /* !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_FORK_H */
diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h
index 4c4025e649..fcf953262c 100644
--- a/usr/src/uts/common/sys/proc.h
+++ b/usr/src/uts/common/sys/proc.h
@@ -27,7 +27,6 @@
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-
#ifndef _SYS_PROC_H
#define _SYS_PROC_H
@@ -432,8 +431,10 @@ extern struct pid pid0; /* p0's pid */
#define SONPROC 6 /* process is being run on a processor */
/* p_pidflag codes */
-#define CLDPEND 0x0001 /* have yet to post a SIGCLD to the parent */
-#define CLDCONT 0x0002 /* child has notified parent of CLD_CONTINUED */
+#define CLDPEND 0x0001 /* have yet to post a SIGCHLD to the parent */
+#define CLDCONT 0x0002 /* child has notified parent of CLD_CONTINUED */
+#define CLDNOSIGCHLD 0x0004 /* do not post SIGCHLD when child terminates */
+#define CLDWAITPID 0x0008 /* only waitid(P_PID, pid) can reap the child */
/* p_proc_flag codes -- these flags are mostly private to /proc */
#define P_PR_TRACE 0x0001 /* signal, fault or syscall tracing via /proc */
@@ -466,12 +467,13 @@ extern struct pid pid0; /* p0's pid */
#define SEXTKILLED 0x00000800 /* SKILLED is from another contract */
#define SUGID 0x00002000 /* process was result of set[ug]id exec */
#define SEXECED 0x00004000 /* this process has execed */
-#define SJCTL 0x00010000 /* SIGCLD sent when children stop/continue */
+#define SJCTL 0x00010000 /* SIGCHLD sent when children stop/continue */
#define SNOWAIT 0x00020000 /* children never become zombies */
#define SVFORK 0x00040000 /* child of vfork that has not yet exec'd */
#define SVFWAIT 0x00080000 /* parent of vfork waiting for child to exec */
#define SEXITLWPS 0x00100000 /* have lwps exit within the process */
#define SHOLDFORK 0x00200000 /* hold lwps where they're cloneable */
+#define SVFPARENT 0x00400000 /* parent of vfork, must call vfwait() */
#define SHOLDFORK1 0x00800000 /* hold lwps in place (not cloning) */
#define SCOREDUMP 0x01000000 /* process is dumping core */
#define SMSACCT 0x02000000 /* process is keeping micro-state accounting */
diff --git a/usr/src/uts/common/sys/procfs.h b/usr/src/uts/common/sys/procfs.h
index 673c963a42..b320836182 100644
--- a/usr/src/uts/common/sys/procfs.h
+++ b/usr/src/uts/common/sys/procfs.h
@@ -202,10 +202,13 @@ typedef struct pstatus {
#define PR_AGENT 0x00000080 /* this lwp is the /proc agent lwp */
#define PR_DETACH 0x00000100 /* this is a detached lwp */
#define PR_DAEMON 0x00000200 /* this is a daemon lwp */
+#define PR_IDLE 0x00000400 /* lwp is a cpu's idle thread */
/* The following flags apply to the process, not to an individual lwp */
#define PR_ISSYS 0x00001000 /* this is a system process */
#define PR_VFORKP 0x00002000 /* process is the parent of a vfork()d child */
#define PR_ORPHAN 0x00004000 /* process's process group is orphaned */
+#define PR_NOSIGCHLD 0x00008000 /* process will not generate SIGCHLD on exit */
+#define PR_WAITPID 0x00010000 /* only waitid(P_PID, pid) can reap the child */
/* The following process flags are modes settable by PCSET/PCUNSET */
#define PR_FORK 0x00100000 /* inherit-on-fork is in effect */
#define PR_RLC 0x00200000 /* run-on-last-close is in effect */
@@ -215,7 +218,6 @@ typedef struct pstatus {
#define PR_BPTADJ 0x02000000 /* breakpoint trap pc adjustment is in effect */
#define PR_PTRACE 0x04000000 /* ptrace-compatibility mode is in effect */
#define PR_MSFORK 0x08000000 /* micro-state accounting inherited on fork */
-#define PR_IDLE 0x10000000 /* lwp is a cpu's idle thread */
/*
* See <sys/procfs_isa.h> for possible values of pr_dmodel.
diff --git a/usr/src/uts/common/sys/syscall.h b/usr/src/uts/common/sys/syscall.h
index 1a6412b70b..96cb967023 100644
--- a/usr/src/uts/common/sys/syscall.h
+++ b/usr/src/uts/common/sys/syscall.h
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -26,7 +27,6 @@
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-
#ifndef _SYS_SYSCALL_H
#define _SYS_SYSCALL_H
@@ -52,7 +52,6 @@ extern "C" {
#define SYS_syscall 0
#define SYS_exit 1
#define SYS_forkall 2
-#define SYS_fork SYS_forkall /* historical */
#define SYS_read 3
#define SYS_write 4
#define SYS_open 5
@@ -321,6 +320,13 @@ extern "C" {
#define SYS_adjtime 138
#define SYS_systeminfo 139
#define SYS_seteuid 141
+#define SYS_forksys 142
+ /*
+ * subcodes:
+ * forkx(flags) :: forksys(0, flags)
+ * forkallx(flags) :: forksys(1, flags)
+ * vforkx(flags) :: forksys(2, flags)
+ */
#define SYS_fork1 143
#define SYS_sigtimedwait 144
#define SYS_lwp_info 145
diff --git a/usr/src/uts/intel/ia32/os/syscall.c b/usr/src/uts/intel/ia32/os/syscall.c
index 965fc07c1d..a78fbc62a6 100644
--- a/usr/src/uts/intel/ia32/os/syscall.c
+++ b/usr/src/uts/intel/ia32/os/syscall.c
@@ -603,8 +603,11 @@ post_syscall(long rval1, long rval2)
* This code must be here and not in the bowels of the system
* so that /proc can intercept exit from vfork in a timely way.
*/
- if (code == SYS_vfork && rp->r_r1 == 0 && error == 0)
+ if (p->p_flag & SVFPARENT) {
+ ASSERT(code == SYS_vfork || code == SYS_forksys);
+ ASSERT(rp->r_r1 == 0 && error == 0);
vfwait((pid_t)rval1);
+ }
/*
* If profiling is active, bill the current PC in user-land
diff --git a/usr/src/uts/intel/os/name_to_sysnum b/usr/src/uts/intel/os/name_to_sysnum
index aebf29f2f2..d6e2f07c71 100644
--- a/usr/src/uts/intel/os/name_to_sysnum
+++ b/usr/src/uts/intel/os/name_to_sysnum
@@ -125,6 +125,7 @@ sysconfig 137
adjtime 138
systeminfo 139
seteuid 141
+forksys 142
fork1 143
sigwait 144
lwp_info 145
diff --git a/usr/src/uts/sparc/os/name_to_sysnum b/usr/src/uts/sparc/os/name_to_sysnum
index 13cf3f5e16..cd9b18215a 100644
--- a/usr/src/uts/sparc/os/name_to_sysnum
+++ b/usr/src/uts/sparc/os/name_to_sysnum
@@ -124,6 +124,7 @@ sysconfig 137
adjtime 138
systeminfo 139
seteuid 141
+forksys 142
fork1 143
sigwait 144
lwp_info 145
diff --git a/usr/src/uts/sparc/os/syscall.c b/usr/src/uts/sparc/os/syscall.c
index d3b16aa5ad..3d11c7f88a 100644
--- a/usr/src/uts/sparc/os/syscall.c
+++ b/usr/src/uts/sparc/os/syscall.c
@@ -708,8 +708,11 @@ post_syscall(long rval1, long rval2)
* This code must be here and not in the bowels of the system
* so that /proc can intercept exit from vfork in a timely way.
*/
- if (code == SYS_vfork && rp->r_o1 == 0 && error == 0)
+ if (p->p_flag & SVFPARENT) {
+ ASSERT(code == SYS_vfork || code == SYS_forksys);
+ ASSERT(rp->r_o1 == 0 && error == 0);
vfwait((pid_t)rval1);
+ }
/*
* If profiling is active, bill the current PC in user-land