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:
parent
cffeda3ce2
commit
2c4ab9ddfa
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user