summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/exit.c')
-rw-r--r--usr/src/uts/common/os/exit.c79
1 files changed, 75 insertions, 4 deletions
diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c
index 7c5b8323e3..612e936540 100644
--- a/usr/src/uts/common/os/exit.c
+++ b/usr/src/uts/common/os/exit.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011, 2014 Joyent, Inc. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -345,6 +345,8 @@ proc_exit(int why, int what)
refstr_t *cwd;
hrtime_t hrutime, hrstime;
int evaporate;
+ brand_t *orig_brand = NULL;
+ void *brand_data = NULL;
/*
* Stop and discard the process's lwps except for the current one,
@@ -374,10 +376,16 @@ proc_exit(int why, int what)
* is always the last lwp, will also perform lwp_exit and free brand
* data
*/
+ mutex_enter(&p->p_lock);
if (PROC_IS_BRANDED(p)) {
+ orig_brand = p->p_brand;
+ if (p->p_brand_data != NULL && orig_brand->b_data_size > 0) {
+ brand_data = p->p_brand_data;
+ }
lwp_detach_brand_hdlrs(lwp);
brand_clearbrand(p, B_FALSE);
}
+ mutex_exit(&p->p_lock);
/*
* Don't let init exit unless zone_start_init() failed its exec, or
@@ -839,8 +847,60 @@ proc_exit(int why, int what)
mutex_exit(&p->p_lock);
if (!evaporate) {
- p->p_pidflag &= ~CLDPEND;
- sigcld(p, sqp);
+ /*
+ * The brand specific code only happens when the brand has a
+ * function to call in place of sigcld, the data itself still
+ * existed, and the parent of the exiting process is not the
+ * global zone init. If the parent is the global zone init,
+ * then the process was reparented, and we don't want brand
+ * code delivering possibly strange signals to init. Also, init
+ * is not branded, so any brand specific exit data will not be
+ * picked up by init anyway.
+ * It is assumed by this code that any brand where
+ * b_exit_with_sig == NULL, will free its own brand_data rather
+ * than letting this piece of code free it.
+ */
+ if (orig_brand != NULL &&
+ orig_brand->b_ops->b_exit_with_sig != NULL &&
+ brand_data != NULL && p->p_ppid != 1) {
+ /*
+ * The code for _fini that could unload the brand_t
+ * blocks until the count of zones using the module
+ * reaches zero. Zones decrement the refcount on their
+ * brands only after all user tasks in that zone have
+ * exited and been waited on. The decrement on the
+ * brand's refcount happen in zone_destroy(). That
+ * depends on zone_shutdown() having been completed.
+ * zone_shutdown() includes a call to zone_empty(),
+ * where the zone waits for itself to reach the state
+ * ZONE_IS_EMPTY. This state is only set in either
+ * zone_shutdown(), when there are no user processes as
+ * the zone enters this function, or in
+ * zone_task_rele(). zone_task_rele() is called from
+ * code triggered by waiting on processes, not by the
+ * processes exiting through proc_exit(). This means
+ * all the branded processes that could exist for a
+ * specific brand_t must exit and get reaped before the
+ * refcount on the brand_t can reach 0. _fini will
+ * never unload the corresponding brand module before
+ * proc_exit finishes execution for all processes
+ * branded with a particular brand_t, which makes the
+ * operation below safe to do. Brands that wish to use
+ * this mechanism must wait in _fini as described
+ * above.
+ */
+ orig_brand->b_ops->b_exit_with_sig(p,
+ sqp, brand_data);
+ } else {
+ p->p_pidflag &= ~CLDPEND;
+ sigcld(p, sqp);
+ }
+ if (brand_data != NULL) {
+ kmem_free(brand_data, orig_brand->b_data_size);
+ brand_data = NULL;
+ orig_brand = NULL;
+ }
+
} else {
/*
* Do what sigcld() would do if the disposition
@@ -950,7 +1010,8 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
pp = ttoproc(curthread);
/*
- * lock parent mutex so that sibling chain can be searched.
+ * Anytime you are looking for a process, you take pidlock to prevent
+ * things from changing as you look.
*/
mutex_enter(&pidlock);
@@ -981,6 +1042,11 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
continue;
if (idtype == P_PGID && id != cp->p_pgrp)
continue;
+ if (PROC_IS_BRANDED(pp)) {
+ if (BROP(pp)->b_wait_filter != NULL &&
+ BROP(pp)->b_wait_filter(pp, cp) == B_FALSE)
+ continue;
+ }
switch (cp->p_wcode) {
@@ -1031,6 +1097,11 @@ waitid(idtype_t idtype, id_t id, k_siginfo_t *ip, int options)
continue;
if (idtype == P_PGID && id != cp->p_pgrp)
continue;
+ if (PROC_IS_BRANDED(pp)) {
+ if (BROP(pp)->b_wait_filter != NULL &&
+ BROP(pp)->b_wait_filter(pp, cp) == B_FALSE)
+ continue;
+ }
switch (cp->p_wcode) {
case CLD_TRAPPED: