Index: sys/compat/svr4/svr4_misc.c =================================================================== RCS file: /usr/cvs/src/sys/compat/svr4/svr4_misc.c,v retrieving revision 1.42 diff -u -r1.42 svr4_misc.c --- sys/compat/svr4/svr4_misc.c 2002/03/20 10:32:01 1.42 +++ sys/compat/svr4/svr4_misc.c 2002/04/27 03:01:42 @@ -1330,8 +1330,14 @@ /* * Remove unused arguments */ - if (q->p_args && --q->p_args->ar_ref == 0) - FREE(q->p_args, M_PARGS); + if (q->p_args) { + PARGS_LOCK(); + if (--q->p_args->ar_ref == 0) { + PARGS_UNLOCK(); + FREE(q->p_args, M_PARGS); + } else + PARGS_UNLOCK(); + } PROC_UNLOCK(q); /* Index: sys/kern/kern_exec.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_exec.c,v retrieving revision 1.156 diff -u -r1.156 kern_exec.c --- sys/kern/kern_exec.c 2002/03/19 21:24:06 1.156 +++ sys/kern/kern_exec.c 2002/04/27 02:57:18 @@ -441,8 +441,14 @@ pa = p->p_args; p->p_args = NULL; PROC_UNLOCK(p); - if (pa != NULL && --pa->ar_ref == 0) - FREE(pa, M_PARGS); + if (pa != NULL) { + PARGS_LOCK(); + if (--pa->ar_ref == 0) { + PARGS_UNLOCK(); + FREE(pa, M_PARGS); + } else + PARGS_UNLOCK(); + } /* Set values passed into the program in registers. */ setregs(td, imgp->entry_addr, (u_long)(uintptr_t)stack_base, Index: sys/kern/kern_exit.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_exit.c,v retrieving revision 1.152 diff -u -r1.152 kern_exit.c --- sys/kern/kern_exit.c 2002/03/20 04:09:58 1.152 +++ sys/kern/kern_exit.c 2002/04/27 03:16:16 @@ -637,8 +637,14 @@ /* * Remove unused arguments */ - if (p->p_args && --p->p_args->ar_ref == 0) - FREE(p->p_args, M_PARGS); + if (p->p_args) { + PARGS_LOCK(); + if (--p->p_args->ar_ref == 0) { + PARGS_UNLOCK(); + FREE(p->p_args, M_PARGS); + } else + PARGS_UNLOCK(); + } if (--p->p_procsig->ps_refcnt == 0) { if (p->p_sigacts != &p->p_uarea->u_sigacts) Index: sys/kern/kern_fork.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_fork.c,v retrieving revision 1.139 diff -u -r1.139 kern_fork.c --- sys/kern/kern_fork.c 2002/03/21 02:47:51 1.139 +++ sys/kern/kern_fork.c 2002/04/27 02:59:20 @@ -482,8 +482,11 @@ p2->p_ucred = crhold(p1->p_ucred); td2->td_ucred = crhold(p2->p_ucred); /* XXXKSE */ - if (p2->p_args) + if (p2->p_args) { + PARGS_LOCK(); p2->p_args->ar_ref++; + PARGS_UNLOCK(); + } if (flags & RFSIGSHARE) { p2->p_procsig = p1->p_procsig; Index: sys/kern/kern_proc.c =================================================================== RCS file: /usr/cvs/src/sys/kern/kern_proc.c,v retrieving revision 1.118 diff -u -r1.118 kern_proc.c --- sys/kern/kern_proc.c 2002/03/24 05:09:11 1.118 +++ sys/kern/kern_proc.c 2002/04/27 04:07:16 @@ -80,6 +80,7 @@ struct sx allproc_lock; struct sx proctree_lock; struct sx pgrpsess_lock; +struct mtx pargs_ref_lock; uma_zone_t proc_zone; uma_zone_t ithread_zone; @@ -94,6 +95,7 @@ sx_init(&allproc_lock, "allproc"); sx_init(&proctree_lock, "proctree"); sx_init(&pgrpsess_lock, "pgrpsess"); + mtx_init(&pargs_ref_lock, "struct pargs.ref",MTX_DEF); LIST_INIT(&allproc); LIST_INIT(&zombproc); pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); @@ -982,8 +984,15 @@ pa = p->p_args; p->p_args = NULL; PROC_UNLOCK(p); - if (pa != NULL && --pa->ar_ref == 0) - FREE(pa, M_PARGS); + + PARGS_LOCK(); + if (pa != NULL) { + if (--pa->ar_ref == 0) { + PARGS_UNLOCK(); + FREE(pa, M_PARGS); + } else + PARGS_UNLOCK(); + } if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) return (error); Index: sys/sys/proc.h =================================================================== RCS file: /usr/cvs/src/sys/sys/proc.h,v retrieving revision 1.211 diff -u -r1.211 proc.h --- sys/sys/proc.h 2002/03/20 21:09:09 1.211 +++ sys/sys/proc.h 2002/04/27 03:07:31 @@ -111,9 +111,9 @@ * pargs, used to hold a copy of the command line, if it had a sane length. */ struct pargs { - u_int ar_ref; /* Reference count. */ - u_int ar_length; /* Length. */ - u_char ar_args[0]; /* Arguments. */ + u_int ar_ref; /* Reference count. */ + u_int ar_length; /* Length. */ + u_char ar_args[0]; /* Arguments. */ }; /*- @@ -668,6 +668,10 @@ (--(p)->p_lock); \ } while (0) +/* Lock and unlock the process arguments. */ +#define PARGS_LOCK() mtx_lock(&pargs_ref_lock) +#define PARGS_UNLOCK() mtx_unlock(&pargs_ref_lock) + #define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash]) extern LIST_HEAD(pidhashhead, proc) *pidhashtbl; extern u_long pidhash; @@ -679,6 +683,7 @@ extern struct sx allproc_lock; extern struct sx proctree_lock; extern struct sx pgrpsess_lock; +extern struct mtx pargs_ref_lock; extern struct proc proc0; /* Process slot for swapper. */ extern struct thread thread0; /* Primary thread in proc0 */ extern int hogticks; /* Limit on kernel cpu hogs. */