Make linux_sendsig and linux_sigreturn use all 64 bits of a

linux_sigset_t by updating the linux_sigframe struct so as to include
linux's "extramask" field.  This field contains the upper 32-bits of
the sigset.  extramask sits behind a linux_fpstate struct, which I've
defined primarily for padding purposes.

While we're here, define LINUX_NSIG in terms of LINUX_NBPW (32) and
LINUX_NSIG_WORDS (2).

This fixes problems where threaded apps would accumulate a large
number of zombies.  This was happening because the exit signal resides
in the upper 32-bits of the sigset and was never getting unmasked by
the manager thread after the first child exited.

PR: 		misc/18530  (may be related, originator not yet contacted)
Reviewed by:	marcel
This commit is contained in:
Andrew Gallatin 2000-11-13 20:44:05 +00:00
parent cffeda3ce2
commit 2c4ab9ddfa
2 changed files with 56 additions and 5 deletions

View File

@ -135,8 +135,10 @@ struct linux_new_utsname {
#define LINUX_SIGPWR 30
#define LINUX_SIGUNUSED 31
#define LINUX_NSIG 64
#define LINUX_SIGTBLSZ 31
#define LINUX_NSIG_WORDS 2
#define LINUX_NBPW 32
#define LINUX_NSIG (LINUX_NBPW * LINUX_NSIG_WORDS)
/* sigaction flags */
#define LINUX_SA_NOCLDSTOP 0x00000001
@ -174,7 +176,7 @@ typedef void (*linux_handler_t)(int);
typedef u_long linux_osigset_t;
typedef struct {
u_int __bits[2];
u_int __bits[LINUX_NSIG_WORDS];
} linux_sigset_t;
typedef struct {
@ -289,6 +291,42 @@ typedef struct siginfo {
#define lsi_band _sifields._sigpoll._band
#define lsi_fd _sifields._sigpoll._fd
struct linux_fpreg {
u_int16_t significand[4];
u_int16_t exponent;
};
struct linux_fpxreg {
u_int16_t significand[4];
u_int16_t exponent;
u_int16_t padding[3];
};
struct linux_xmmreg {
u_int32_t element[4];
};
struct linux_fpstate {
/* Regular FPU environment */
u_int32_t cw;
u_int32_t sw;
u_int32_t tag;
u_int32_t ipoff;
u_int32_t cssel;
u_int32_t dataoff;
u_int32_t datasel;
struct linux_fpreg _st[8];
u_int16_t status;
u_int16_t magic; /* 0xffff = regular FPU data */
/* FXSR FPU environment */
u_int32_t _fxsr_env[6]; /* env is ignored */
u_int32_t mxcsr;
u_int32_t reserved;
struct linux_fpxreg _fxsr_st[8]; /* reg data is ignored */
struct linux_xmmreg _xmm[8];
u_int32_t padding[56];
};
/*
* We make the stack look like Linux expects it when calling a signal
@ -299,6 +337,8 @@ typedef struct siginfo {
struct linux_sigframe {
int sf_sig;
struct linux_sigcontext sf_sc;
struct linux_fpstate fpstate;
u_int extramask[LINUX_NSIG_WORDS-1];
linux_handler_t sf_handler;
};

View File

@ -345,7 +345,7 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
register struct trapframe *regs;
struct linux_sigframe *fp, frame;
struct sigacts *psp = p->p_sigacts;
int oonstack;
int oonstack, i;
regs = p->p_md.md_regs;
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
@ -425,7 +425,10 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame.sf_sc.sc_ss = regs->tf_ss;
frame.sf_sc.sc_err = regs->tf_err;
frame.sf_sc.sc_trapno = code; /* XXX ???? */
bzero(&frame.fpstate, sizeof(struct linux_fpstate));
for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
frame.extramask[i] = mask->__bits[i+1];
if (copyout(&frame, fp, sizeof(frame)) != 0) {
/*
* Process has trashed its stack; give it an illegal
@ -466,7 +469,9 @@ linux_sigreturn(p, args)
{
struct linux_sigcontext context;
register struct trapframe *regs;
int eflags;
u_int extramask[LINUX_NSIG_WORDS-1];
u_int *emp;
int eflags, i;
regs = p->p_md.md_regs;
@ -513,6 +518,12 @@ linux_sigreturn(p, args)
}
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
emp = (u_int *)((caddr_t)args->scp + sizeof(context) +
sizeof(struct linux_fpstate));
if (copyin((caddr_t)emp, extramask, sizeof(extramask)) == 0)
for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
p->p_sigmask.__bits[i+1] = extramask[i];
SIGSETOLD(p->p_sigmask, context.sc_mask);
SIG_CANTMASK(p->p_sigmask);