diff options
author | raf <none@none> | 2006-12-13 11:41:29 -0800 |
---|---|---|
committer | raf <none@none> | 2006-12-13 11:41:29 -0800 |
commit | 657b1f3d64bcf8eaa2385dba72a6047f089433b2 (patch) | |
tree | f39954fcde5cecefa713fa403e7e4b55a83f7c0d /usr/src | |
parent | 7b55fa8ea6046becb3b72f8886a503979c322084 (diff) | |
download | illumos-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')
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 |