In stange circumstances we may end up being the last reference to a

session in tprintf().   SESSRELE() needs to properly dispose of the
sessions mutex.

Add sessrele() which does the proper cleanup and have SESSRELE() call it.

Use SESSRELE also in pgdelete().

Found by:	Coverity (ID:526)
This commit is contained in:
Poul-Henning Kamp 2005-03-17 08:44:41 +00:00
parent 0e41462ff3
commit 572b4402d1
3 changed files with 21 additions and 18 deletions

View File

@ -429,7 +429,6 @@ pgdelete(pgrp)
register struct pgrp *pgrp;
{
struct session *savesess;
int i;
sx_assert(&proctree_lock, SX_XLOCKED);
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
@ -447,16 +446,8 @@ pgdelete(pgrp)
pgrp->pg_session->s_ttyp->t_pgrp = NULL;
LIST_REMOVE(pgrp, pg_hash);
savesess = pgrp->pg_session;
SESS_LOCK(savesess);
i = --savesess->s_count;
SESS_UNLOCK(savesess);
SESSRELE(savesess);
PGRP_UNLOCK(pgrp);
if (i == 0) {
if (savesess->s_ttyp != NULL)
ttyrel(savesess->s_ttyp);
mtx_destroy(&savesess->s_mtx);
FREE(savesess, M_SESSION);
}
mtx_destroy(&pgrp->pg_mtx);
FREE(pgrp, M_PGRP);
}
@ -560,6 +551,22 @@ orphanpg(pg)
}
}
void
sessrele(struct session *s)
{
int i;
SESS_LOCK(s);
i = --s->s_count;
SESS_UNLOCK(s);
if (i == 0) {
if (s->s_ttyp != NULL)
ttyrel(s->s_ttyp);
mtx_destroy(&s->s_mtx);
FREE(s, M_SESSION);
}
}
#include "opt_ddb.h"
#ifdef DDB
#include <ddb/ddb.h>

View File

@ -189,11 +189,8 @@ tprintf(struct proc *p, int pri, const char *fmt, ...)
va_start(ap, fmt);
kvprintf(fmt, putchar, &pca, 10, ap);
va_end(ap);
if (sess != NULL) {
SESS_LOCK(sess);
if (sess != NULL)
SESSRELE(sess);
SESS_UNLOCK(sess);
}
msgbuftrigger = 1;
}

View File

@ -714,10 +714,8 @@ MALLOC_DECLARE(M_ZOMBIE);
#define SESS_LEADER(p) ((p)->p_session->s_leader == (p))
#define SESSHOLD(s) ((s)->s_count++)
#define SESSRELE(s) { \
if (--(s)->s_count == 0) \
FREE(s, M_SESSION); \
}
#define SESSRELE(s) sessrele(s)
#define STOPEVENT(p, e, v) do { \
if ((p)->p_stops & (e)) { \
@ -860,6 +858,7 @@ void pstats_fork(struct pstats *src, struct pstats *dst);
void pstats_free(struct pstats *ps);
int securelevel_ge(struct ucred *cr, int level);
int securelevel_gt(struct ucred *cr, int level);
void sessrele(struct session *);
void setrunnable(struct thread *);
void setrunqueue(struct thread *, int flags);
void setsugid(struct proc *p);