Beispiel #1
0
/*
 * If pid is positive, then signal sig is sent to the process with the ID specified by pid.
 * If pid equals 0, then sig is sent to every process in the process group of the calling process.
 * If pid equals -1, then sig is sent to every process for which the calling process has permission to send signals, except for process 1 (init), but see below.
 * If pid is less than -1, then sig is sent to every process in the process group whose ID is -pid.
 * If sig is 0, then no signal is sent, but error checking is still performed; this can be used to check for the existence of a process ID or process group ID.
 * */
int do_kill(int pid, int sig){
    struct proc *p;
    int nr, ret;

    if (pid>0)
        return sigsend(pid, sig, 0);
    if (pid==0)
        return sigsend_g(cu->p_pid, sig, 0);
    if (pid < -1)
        return sigsend_g(-pid, sig, 0);
    if (pid==-1) {
        for (nr=1; nr<NPROC; nr++) {
            if ((p=proc[nr]))
                ret = sigsend(nr, sig, 0);
        }
        return ret;
    }
    syserr(EINVAL);
    return -1;
}
Beispiel #2
0
/* send a signal to a process group. */
int sigsend_g(int pgrp, int n, int priv){
    int nr;
    struct proc *p;

    for (nr=0; nr<NPROC; nr++) {
        if ((p=proc[nr]) && p->p_pgrp==pgrp) {
            sigsend(p->p_pid, n, priv);
        }
    }
    return 0;
}
Beispiel #3
0
int 
sys_sigsend(void)
{
  int dest_pid;
  int value;

  if (argint(0, &dest_pid) < 0 || argint(1, &value) < 0)
    return -1;

  return sigsend(dest_pid, value);
}
Beispiel #4
0
int
sys_sigsend(void){
  int pid,signum;
  
  if (argint(0, &pid) <0) {
      return -1;
  }
  if (argint(1, &signum) <0 ) {
      return -1;
  }
  return sigsend(pid, signum);
}
Beispiel #5
0
/* ARGSUSED */
static	void
childcleanup(int sig)
{
	int i;

	/* Only need to kill the child that became the shell. */
	for (i = 0; i < nchild; i++) {
		/* Don't kill gramps before his time */
		if (pidlist[i] != getppid())
			(void) sigsend(P_PID, pidlist[i], SIGHUP);
	}
}
Beispiel #6
0
/*
 * Tells the threadflow's thread to stop and optionally signals
 * its associated process to end the thread.
 */
static void
threadflow_kill(threadflow_t *threadflow)
{
	/* Tell thread to finish */
	threadflow->tf_abort = 1;

#ifdef USE_PROCESS_MODEL
#ifdef HAVE_SIGSEND
	(void) sigsend(P_PID, threadflow->tf_process->pf_pid, SIGUSR1);
#else
	(void) kill(threadflow->tf_process->pf_pid, SIGUSR1);
#endif
#else /* USE_PROCESS_MODEL */
	threadflow->tf_process->pf_running = 0;
#endif /* USE_PROCESS_MODEL */
}
Beispiel #7
0
int
main(int argc, char *argv[])
{
int pid;
void (*fp)(void) = death;
printf(2,"death = %d",(int)fp);

pid = fork();
if (pid==0) {
	printf(2,"death = %d",(int)fp);
	signal(5,death);
	while(1);
}
	sleep(100);
	int j = sigsend(pid,5);
	printf(2,"return val %d",j);
	wait();
return 0;
}
Beispiel #8
0
uint32
runtime·ctrlhandler1(uint32 type)
{
	int32 s;

	switch(type) {
	case CTRL_C_EVENT:
	case CTRL_BREAK_EVENT:
		s = SIGINT;
		break;
	default:
		return 0;
	}

	if(runtime·sigsend(s))
		return 1;
	runtime·exit(2);	// SIGINT, SIGTERM, etc
	return 0;
}
Beispiel #9
0
// Exit the current process.  Does not return.
// An exited process remains in the zombie state
// until its parent calls wait() to find out it exited.
void
exit(void)
{
    struct proc *p;
    int fd;

    if(proc == initproc)
        panic("init exiting");

    // Close all open files.
    for(fd = 0; fd < NOFILE; fd++) {
        if(proc->ofile[fd]) {
            fileclose(proc->ofile[fd]);
            proc->ofile[fd] = 0;
        }
    }

    iput(proc->cwd);
    proc->cwd = 0;

    acquire(&ptable.lock);

    //A&T sent a SIGCHLD to the parent process
    sigsend(proc->parent->pid,SIGCHLD);


    // Parent might be sleeping in wait().
    wakeup1(proc->parent);

    // Pass abandoned children to init.
    for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) {
        if(p->parent == proc) {
            p->parent = initproc;
            if(p->state == ZOMBIE)
                wakeup1(initproc);
        }
    }
    // Jump into the scheduler, never to return.
    proc->state = ZOMBIE;
    sched();
    panic("zombie exit");
}
Beispiel #10
0
/* terminate the currenct proccess into ZOMBIE, and tell its parent.
 * the struct proc is freed by each proc's parent.
 * */
int do_exit(int ret){
    struct file *fp;
    struct proc *p;
    uint fd, nr;

    cu->p_ret = ret;
    // clear all the signal handlers
    for (nr=0; nr<NSIG; nr++) {
        cu->p_sigact[nr].sa_handler = SIG_DFL;
        cu->p_sigact[nr].sa_flags = 0;
    }
    // close all the opened files, and iput the directories.
    for (fd=0; fd<NOFILE; fd++){
        fp = cu->p_ofile[fd];
        if (fp != NULL) {
            do_close(fd);
        }
        cu->p_ofile[fd] = NULL;
    }
    iput(cu->p_iroot);
    iput(cu->p_wdir);
    // tell its parent
    sigsend(cu->p_ppid, SIGCHLD, 1);
    // free the address space
    vm_clear(&cu->p_vm);
    kfree(cu->p_vm.vm_pgd, PAGE);
    // make this process Zombie, give all the children to proc[1] 
    // and tell its parent
    cu->p_chan = 0;
    cu->p_stat = SZOMB;
    for (nr=1; nr<NPROC; nr++) {
        if ((p=proc[nr]) && p!=cu && (p->p_ppid==cu->p_pid)) {
            p->p_ppid = 1;
        }
    }
    // wakeup proc[1] and its parent
    p = proc[cu->p_ppid];
    wakeup(p);
    wakeup(proc[1]);
    return 0;
}
Beispiel #11
0
void
sighandler(int32 sig, Siginfo *info, void *context)
{
	Ucontext *uc;
	Mcontext *mc;
	Regs *r;

	if(sigtab[sig].flags & SigQueue) {
		if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
			return;
		exit(2);	// SIGINT, SIGTERM, etc
	}

	if(panicking)	// traceback already printed
		exit(2);
	panicking = 1;

	if(sig < 0 || sig >= NSIG){
		printf("Signal %d\n", sig);
	}else{
		printf("%s\n", sigtab[sig].name);
	}

	uc = context;
	mc = uc->uc_mcontext;
	r = &mc->ss;

	printf("Faulting address: %p\n", info->si_addr);
	printf("pc: %X\n", r->rip);
	printf("\n");

	if(gotraceback()){
		traceback((void*)r->rip, (void*)r->rsp, (void*)r->r15);
		tracebackothers((void*)r->r15);
		dumpregs(r);
	}

	breakpoint();
	exit(2);
}
Beispiel #12
0
/*
 * Tells the threadflow's thread to stop and optionally signals
 * its associated process to end the thread.
 */
static void
threadflow_kill(threadflow_t *threadflow, int wait_cnt)
{
	/* Tell thread to finish */
	threadflow->tf_abort = 1;

	/* wait a bit for threadflow to stop */
	while (wait_cnt && threadflow->tf_running) {
		(void) sleep(1);
		wait_cnt--;
	}

#ifdef USE_PROCESS_MODEL
#ifdef HAVE_SIGSEND
	(void) sigsend(P_PID, threadflow->tf_process->pf_pid, SIGUSR1);
#else
	(void) kill(threadflow->tf_process->pf_pid, SIGUSR1);
#endif
#else /* USE_PROCESS_MODEL */
	threadflow->tf_process->pf_running = 0;
#endif /* USE_PROCESS_MODEL */
}
Beispiel #13
0
void
sighandler(int32 sig, Siginfo* info, void* context)
{
	Ucontext *uc;
	Mcontext *mc;

	if(sigtab[sig].flags & SigQueue) {
		if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
			return;
		exit(2);	// SIGINT, SIGTERM, etc
	}

	if(panicking)	// traceback already printed
		exit(2);
	panicking = 1;

	uc = context;
	mc = &uc->uc_mcontext;

	if(sig < 0 || sig >= NSIG)
		printf("Signal %d\n", sig);
	else
		printf("%s\n", sigtab[sig].name);

	printf("Faulting address: %p\n", info->si_addr);
	printf("PC=%X\n", mc->mc_eip);
	printf("\n");

	if(gotraceback()){
		traceback((void*)mc->mc_eip, (void*)mc->mc_esp, m->curg);
		tracebackothers(m->curg);
		dumpregs(mc);
	}

	breakpoint();
	exit(2);
}
Beispiel #14
0
/* ARGSUSED */
static void
parenthandler(int sig, siginfo_t *si, ucontext_t *uc)
{
	int i;

	/*
	 * We get here if someone has successfully entered a password
	 * from the auxiliary console and is getting the single-user shell.
	 * When this happens, the parent needs to kill the children
	 * that didn't get the shell.
	 *
	 */
	for (i = 0; i < nchild; i++) {
		if (pidlist[i] != si->__data.__proc.__pid)
			(void) sigsend(P_PID, pidlist[i], SIGTERM);
	}
	sa.sa_handler = SIG_IGN;
	sa.sa_flags = 0;
	(void) sigemptyset(&sa.sa_mask);
	(void) sigaction(SIGINT, &sa, NULL);
	(void) sigaction(SIGQUIT, &sa, NULL);
	(void) sigaction(SIGTERM, &sa, NULL);
	(void) wait(NULL);
}
Beispiel #15
0
void
sighandler(int32 sig, Siginfo *info, void *context)
{
	Ucontext *uc;
	Mcontext *mc;
	Regs *r;
	G *gp;
	uintptr *sp;
	byte *pc;

	uc = context;
	mc = uc->uc_mcontext;
	r = &mc->ss;

	if((gp = m->curg) != nil && (sigtab[sig].flags & SigPanic)) {
		// Work around Leopard bug that doesn't set FPE_INTDIV.
		// Look at instruction to see if it is a divide.
		// Not necessary in Snow Leopard (si_code will be != 0).
		if(sig == SIGFPE && info->si_code == 0) {
			pc = (byte*)r->rip;
			if((pc[0]&0xF0) == 0x40)	// 64-bit REX prefix
				pc++;
			if(pc[0] == 0xF7)
				info->si_code = FPE_INTDIV;
		}
		
		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = info->si_code;
		gp->sigcode1 = (uintptr)info->si_addr;
		
		// Only push sigpanic if r->rip != 0.
		// If r->rip == 0, probably panicked because of a
		// call to a nil func.  Not pushing that onto sp will
		// make the trace look like a call to sigpanic instead.
		// (Otherwise the trace will end at sigpanic and we
		// won't get to see who faulted.)
		if(r->rip != 0) {
			sp = (uintptr*)r->rsp;
			*--sp = r->rip;
			r->rsp = (uintptr)sp;
		}
		r->rip = (uintptr)sigpanic;
		return;
	}

	if(sigtab[sig].flags & SigQueue) {
		if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
			return;
		exit(2);	// SIGINT, SIGTERM, etc
	}

	if(panicking)	// traceback already printed
		exit(2);
	panicking = 1;

	if(sig < 0 || sig >= NSIG){
		printf("Signal %d\n", sig);
	}else{
		printf("%s\n", sigtab[sig].name);
	}

	printf("pc: %X\n", r->rip);
	printf("\n");

	if(gotraceback()){
		traceback((void*)r->rip, (void*)r->rsp, 0, (void*)r->r15);
		tracebackothers((void*)r->r15);
		dumpregs(r);
	}

	breakpoint();
	exit(2);
}
Beispiel #16
0
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
	UcontextT *uc = context;
	McontextT *mc = &uc->uc_mcontext;
	uintptr *sp;
	SigTab *t;

	if(sig == SIGPROF) {
		runtime·sigprof((uint8*)mc->__gregs[REG_EIP],
			(uint8*)mc->__gregs[REG_UESP], nil, gp);
		return;
	}

	t = &runtime·sigtab[sig];
	if(info->_code != SI_USER && (t->flags & SigPanic)) {
		if(gp == nil || gp == m->g0)
			goto Throw;
		// Make it look like a call to the signal func.
		// We need to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = info->_code;
		gp->sigcode1 = *(uintptr*)&info->_reason[0]; /* _addr */
		gp->sigpc = mc->__gregs[REG_EIP];

		// Only push runtime·sigpanic if __gregs[REG_EIP] != 0.
		// If __gregs[REG_EIP] == 0, probably panicked because of a
		// call to a nil func. Not pushing that onto sp will make the
		// trace look like a call to runtime·sigpanic instead.
		// (Otherwise the trace will end at runtime·sigpanic
		// and we won't get to see who faulted.)
		if(mc->__gregs[REG_EIP] != 0) {
			sp = (uintptr*)mc->__gregs[REG_UESP];
			*--sp = mc->__gregs[REG_EIP];
			mc->__gregs[REG_UESP] = (uintptr)sp;
		}
		mc->__gregs[REG_EIP] = (uintptr)runtime·sigpanic;
		return;
	}

	if(info->_code == SI_USER || (t->flags & SigNotify))
		if(runtime·sigsend(sig))
			return;
	if(t->flags & SigKill)
		runtime·exit(2);
	if(!(t->flags & SigThrow))
		return;

Throw:
	runtime·startpanic();

	if(sig < 0 || sig >= NSIG)
		runtime·printf("Signal %d\n", sig);
	else
		runtime·printf("%s\n", runtime·sigtab[sig].name);

	runtime·printf("PC=%X\n", mc->__gregs[REG_EIP]);
	if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
		runtime·printf("signal arrived during cgo execution\n");
		gp = m->lockedg;
	}
	runtime·printf("\n");

	if(runtime·gotraceback()){
		runtime·traceback((void*)mc->__gregs[REG_EIP],
			(void*)mc->__gregs[REG_UESP], 0, gp);
		runtime·tracebackothers(gp);
		runtime·dumpregs(mc);
	}

	runtime·exit(2);
}
Beispiel #17
0
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
	Ucontext *uc;
	Sigcontext *r;
	SigTab *t;

	uc = context;
	r = &uc->uc_mcontext;

	if(sig == SIGPROF) {
		runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, gp);
		return;
	}

	t = &runtime·sigtab[sig];
	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
		if(gp == nil)
			goto Throw;
		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = info->si_code;
		gp->sigcode1 = r->fault_address;
		gp->sigpc = r->arm_pc;

		// If this is a leaf function, we do smash LR,
		// but we're not going back there anyway.
		// Don't bother smashing if r->arm_pc is 0,
		// which is probably a call to a nil func: the
		// old link register is more useful in the stack trace.
		if(r->arm_pc != 0)
			r->arm_lr = r->arm_pc;
		// In case we are panicking from external C code
		r->arm_r10 = (uintptr)gp;
		r->arm_r9 = (uintptr)m;
		r->arm_pc = (uintptr)runtime·sigpanic;
		return;
	}

	if(info->si_code == SI_USER || (t->flags & SigNotify))
		if(runtime·sigsend(sig))
			return;
	if(t->flags & SigKill)
		runtime·exit(2);
	if(!(t->flags & SigThrow))
		return;

Throw:
	if(runtime·panicking)	// traceback already printed
		runtime·exit(2);
	runtime·panicking = 1;

	if(sig < 0 || sig >= NSIG)
		runtime·printf("Signal %d\n", sig);
	else
		runtime·printf("%s\n", runtime·sigtab[sig].name);

	runtime·printf("PC=%x\n", r->arm_pc);
	runtime·printf("\n");

	if(runtime·gotraceback()){
		runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp);
		runtime·tracebackothers(gp);
		runtime·printf("\n");
		runtime·dumpregs(r);
	}

//	breakpoint();
	runtime·exit(2);
}
Beispiel #18
0
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
	Ucontext *uc;
	Sigcontext *r;
	uintptr *sp;
	SigTab *t;

	uc = context;
	r = &uc->uc_mcontext;

	if(sig == SIGPROF) {
		runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
		return;
	}

	t = &runtime·sigtab[sig];
	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
		if(gp == nil)
			goto Throw;
		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = info->si_code;
		gp->sigcode1 = ((uintptr*)info)[3];
		gp->sigpc = r->eip;

		// Only push runtime·sigpanic if r->eip != 0.
		// If r->eip == 0, probably panicked because of a
		// call to a nil func.  Not pushing that onto sp will
		// make the trace look like a call to runtime·sigpanic instead.
		// (Otherwise the trace will end at runtime·sigpanic and we
		// won't get to see who faulted.)
		if(r->eip != 0) {
			sp = (uintptr*)r->esp;
			*--sp = r->eip;
			r->esp = (uintptr)sp;
		}
		r->eip = (uintptr)runtime·sigpanic;
		return;
	}

	if(info->si_code == SI_USER || (t->flags & SigNotify))
		if(runtime·sigsend(sig))
			return;
	if(t->flags & SigKill)
		runtime·exit(2);
	if(!(t->flags & SigThrow))
		return;

Throw:
	runtime·startpanic();

	if(sig < 0 || sig >= NSIG)
		runtime·printf("Signal %d\n", sig);
	else
		runtime·printf("%s\n", runtime·sigtab[sig].name);

	runtime·printf("PC=%X\n", r->eip);
	runtime·printf("\n");

	if(runtime·gotraceback()){
		runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
		runtime·tracebackothers(gp);
		runtime·dumpregs(r);
	}

	runtime·exit(2);
}
Beispiel #19
0
void ctrlc(void){
	if(lastShInvokedPid != -1)
		sigsend(lastShInvokedPid, SIGINT); 

}
Beispiel #20
0
int main(int argc, char *argv[]) {

	int parent_pid = getpid();
	int worker_pid;
	if(argc != 2){
		printf(1,"Needs 2 arguments... Try again.\n");
		exit();
	}
	int n = atoi(argv[1]);
	if(n > NPROC){
		printf(1,"Too many workers, can't handle it!!!! Goodbye...\n");
		exit();
	}

	int i = 0;
	sigset(&parent_handler);
	printf(1, "workers pids:\n");
	for (i = 0; i < n; i++) { //creating n processes
		worker_pid = fork();
		if (worker_pid < 0)
			break;
		if (worker_pid == 0) { //child process
			sigset(&worker_handler); // init sig_handler of the child process
			while (1) {
				sigpause();
			}
		} else {
			workers[i].pid = worker_pid;
			workers[i].free = 1;
			printf(1, "%d\n", worker_pid);

		}
	}
	if (getpid() == parent_pid) {
		char buf[128];
		for (;;) {
//			sleep(1);
			printf(1, "please enter a number: ");
			read(1, buf, 128);
			if (strlen(buf) == 1 && buf[0] == '\n')
				continue;
			int x = atoi(buf);
			if (x < 0){ //Doesn't support negative numbers (or bigger than max_integer)
				x = 1;
				printf(1,"Primsrv doesn't support your number :( changing it to 1...\n");
			}
			memset(buf, '\0', 128);
			if (x == 0) { //need to exit program
				for (i = 0; i < n; i++) {
					sigsend(workers[i].pid, x);
				}
				int pid;
				while ((pid = wait()) > -1)
					printf(1, "worker %d exit\n", pid);
				printf(1, "primsrv exit\n");
				break;
			} else { //search for idle worker
				i = 0;
				while (i < n && !workers[i].free) {

					i++;
				}
				if (i == n) {
					printf(1, "no idle workers\n");
					continue;
				} else {
					workers[i].free = 0;
					workers[i].last_number = x;
					sigsend(workers[i].pid, x);
				}
			}
		}
	}
	exit();
}
Beispiel #21
0
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
    Ucontext *uc;
    Sigcontext *r;
    SigTab *t;

    uc = context;
    r = &uc->uc_mcontext;

    if(sig == SIGPROF) {
        runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, gp);
        return;
    }

    t = &runtime·sigtab[sig];
    if(info->si_code != SI_USER && (t->flags & SigPanic)) {
        if(gp == nil || gp == m->g0)
            goto Throw;
        // Make it look like a call to the signal func.
        // Have to pass arguments out of band since
        // augmenting the stack frame would break
        // the unwinding code.
        gp->sig = sig;
        gp->sigcode0 = info->si_code;
        gp->sigcode1 = r->fault_address;
        gp->sigpc = r->arm_pc;

        // We arrange lr, and pc to pretend the panicking
        // function calls sigpanic directly.
        // Always save LR to stack so that panics in leaf
        // functions are correctly handled. This smashes
        // the stack frame but we're not going back there
        // anyway.
        r->arm_sp -= 4;
        *(uint32 *)r->arm_sp = r->arm_lr;
        // Don't bother saving PC if it's zero, which is
        // probably a call to a nil func: the old link register
        // is more useful in the stack trace.
        if(r->arm_pc != 0)
            r->arm_lr = r->arm_pc;
        // In case we are panicking from external C code
        r->arm_r10 = (uintptr)gp;
        r->arm_r9 = (uintptr)m;
        r->arm_pc = (uintptr)runtime·sigpanic;
        return;
    }

    if(info->si_code == SI_USER || (t->flags & SigNotify))
        if(runtime·sigsend(sig))
            return;
    if(t->flags & SigKill)
        runtime·exit(2);
    if(!(t->flags & SigThrow))
        return;

Throw:
    if(runtime·panicking)	// traceback already printed
        runtime·exit(2);
    runtime·panicking = 1;

    if(sig < 0 || sig >= NSIG)
        runtime·printf("Signal %d\n", sig);
    else
        runtime·printf("%s\n", runtime·sigtab[sig].name);

    runtime·printf("PC=%x\n", r->arm_pc);
    if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
        runtime·printf("signal arrived during cgo execution\n");
        gp = m->lockedg;
    }
    runtime·printf("\n");

    if(runtime·gotraceback()) {
        runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp);
        runtime·tracebackothers(gp);
        runtime·printf("\n");
        runtime·dumpregs(r);
    }

//	breakpoint();
    runtime·exit(2);
}
Beispiel #22
0
int
pkgexecv(char *filein, char *fileout, char *uname, char *gname, char *arg[])
{
	int			exit_no;
	int			n;
	int			status;
	pid_t			pid;
	pid_t			waitstat;
	struct group		*grp;
	struct passwd		*pwp;
	struct sigaction	nact;
	struct sigaction	oact;
	void			(*funcSighup)(int);
	void			(*funcSigint)(int);

	/* flush standard i/o before creating new process */

	(void) fflush(stdout);
	(void) fflush(stderr);

	/*
	 * hold SIGINT/SIGHUP signals and reset signal received counter;
	 * after the vfork() the parent and child need to setup their respective
	 * interrupt handling and release the hold on the signals
	 */

	(void) sighold(SIGINT);
	(void) sighold(SIGHUP);

	sig_received = 0;

	/*
	 * create new process to execute command in;
	 * vfork() is being used to avoid duplicating the parents
	 * memory space - this means that the child process may
	 * not modify any of the parents memory including the
	 * standard i/o descriptors - all the child can do is
	 * adjust interrupts and open files as a prelude to a
	 * call to exec().
	 */

	pid = vfork();

	if (pid < 0) {
		/*
		 * *************************************************************
		 * fork failed!
		 * *************************************************************
		 */

		progerr(pkg_gt(ERR_FORK_FAILED), errno, strerror(errno));

		/* release hold on signals */

		(void) sigrelse(SIGHUP);
		(void) sigrelse(SIGINT);

		return (-1);
	}

	if (pid > 0) {
		/*
		 * *************************************************************
		 * This is the forking (parent) process
		 * *************************************************************
		 */

		/* close datastream if any portion read */

		if (ds_curpartcnt >= 0) {
			if (ds_close(0) != 0) {
				/* kill child process */

				(void) sigsend(P_PID, pid, SIGKILL);

				/* release hold on signals */

				(void) sigrelse(SIGHUP);
				(void) sigrelse(SIGINT);

				return (-1);
			}
		}

		/*
		 * setup signal handlers for SIGINT and SIGHUP and release hold
		 */

		/* hook SIGINT to sig_trap() */

		nact.sa_handler = sig_trap;
		nact.sa_flags = SA_RESTART;
		(void) sigemptyset(&nact.sa_mask);

		if (sigaction(SIGINT, &nact, &oact) < 0) {
			funcSigint = SIG_DFL;
		} else {
			funcSigint = oact.sa_handler;
		}

		/* hook SIGHUP to sig_trap() */

		nact.sa_handler = sig_trap;
		nact.sa_flags = SA_RESTART;
		(void) sigemptyset(&nact.sa_mask);

		if (sigaction(SIGHUP, &nact, &oact) < 0) {
			funcSighup = SIG_DFL;
		} else {
			funcSighup = oact.sa_handler;
		}

		/* release hold on signals */

		(void) sigrelse(SIGHUP);
		(void) sigrelse(SIGINT);

		/*
		 * wait for the process to exit, reap child exit status
		 */

		for (;;) {
			status = 0;
			waitstat = waitpid(pid, (int *)&status, 0);
			if (waitstat < 0) {
				/* waitpid returned error */
				if (errno == EAGAIN) {
					/* try again */
					continue;
				}
				if (errno == EINTR) {
					continue;
				}
				/* error from waitpid: bail */
				break;
			} else if (waitstat == pid) {
				/* child exit status available */
				break;
			}
		}

		/*
		 * reset signal handlers
		 */

		/* reset SIGINT */

		nact.sa_handler = funcSigint;
		nact.sa_flags = SA_RESTART;
		(void) sigemptyset(&nact.sa_mask);

		(void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);

		/* reset SIGHUP */

		nact.sa_handler = funcSighup;
		nact.sa_flags = SA_RESTART;
		(void) sigemptyset(&nact.sa_mask);

		(void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);

		/* error if child process does not match */

		if (waitstat != pid) {
			progerr(pkg_gt(ERR_WAIT_FAILED), pid, waitstat, status,
				errno, strerror(errno));
			return (-1);
		}

		/*
		 * determine final exit code:
		 * - if signal received, then return interrupted (3)
		 * - if child exit status is available, return exit child status
		 * - otherwise return error (-1)
		 */

		if (sig_received != 0) {
			exit_no = 3;	/* interrupted */
		} else if (WIFEXITED(status)) {
			exit_no = WEXITSTATUS(status);
		} else {
			exit_no = -1;	/* exec() or other process error */
		}

		return (exit_no);
	}

	/*
	 * *********************************************************************
	 * This is the forked (child) process
	 * *********************************************************************
	 */

	/* reset all signals to default */

	for (n = 0; n < NSIG; n++) {
		(void) sigset(n, SIG_DFL);
	}

	/* release hold on signals held by parent before fork() */

	(void) sigrelse(SIGHUP);
	(void) sigrelse(SIGINT);

	/*
	 * The caller wants to have stdin connected to filein.
	 */

	if (filein && *filein) {
		/*
		 * If input is supposed to be connected to /dev/tty
		 */
		if (strncmp(filein, "/dev/tty", 8) == 0) {
			/*
			 * If stdin is connected to a tty device.
			 */
			if (isatty(STDIN_FILENO)) {
				/*
				 * Reopen it to /dev/tty.
				 */
				n = open(filein, O_RDONLY);
				if (n >= 0) {
					(void) dup2(n, STDIN_FILENO);
				}
			}
		} else {
			/*
			 * If we did not want to be connected to /dev/tty, we
			 * connect input to the requested file no questions.
			 */
			n = open(filein, O_RDONLY);
			if (n >= 0) {
				(void) dup2(n, STDIN_FILENO);
			}
		}
	}

	/*
	 * The caller wants to have stdout and stderr connected to fileout.
	 * If "fileout" is "/dev/tty" then reconnect stdout to "/dev/tty"
	 * only if /dev/tty is not already associated with "a tty".
	 */

	if (fileout && *fileout) {
		/*
		 * If output is supposed to be connected to /dev/tty
		 */
		if (strncmp(fileout, "/dev/tty", 8) == 0) {
			/*
			 * If stdout is connected to a tty device.
			 */
			if (isatty(STDOUT_FILENO)) {
				/*
				 * Reopen it to /dev/tty if /dev/tty available.
				 */
				n = open(fileout, O_WRONLY);
				if (n >= 0) {
					/*
					 * /dev/tty is available - close the
					 * current standard output stream, and
					 * reopen it on /dev/tty
					 */
					(void) dup2(n, STDOUT_FILENO);
				}
			}
			/*
			 * not connected to tty device - probably redirect to
			 * file - preserve existing output device
			 */
		} else {
			/*
			 * If we did not want to be connected to /dev/tty, we
			 * connect output to the requested file no questions.
			 */
			/* LINTED O_CREAT without O_EXCL specified in call to */
			n = open(fileout, O_WRONLY|O_CREAT|O_APPEND, 0666);
			if (n >= 0) {
				(void) dup2(n, STDOUT_FILENO);
			}
		}

		/*
		 * Dup stderr from stdout.
		 */

		(void) dup2(STDOUT_FILENO, STDERR_FILENO);
	}

	/*
	 * do NOT close all file descriptors except stdio
	 * file descriptors are passed in to some subcommands
	 * (see dstream:ds_getinfo() and dstream:ds_putinfo())
	 */

	/* set group/user i.d. if requested */

	if (gname && *gname && (grp = cgrnam(gname)) != NULL) {
		if (setgid(grp->gr_gid) == -1) {
			progerr(pkg_gt(ERR_SETGID), grp->gr_gid);
		}
	}
	if (uname && *uname && (pwp = cpwnam(uname)) != NULL) {
		if (setuid(pwp->pw_uid) == -1) {
			progerr(pkg_gt(ERR_SETUID), pwp->pw_uid);
		}
	}

	/* execute target executable */

	(void) execve(arg[0], arg, environ);
	progerr(pkg_gt(ERR_EX_FAIL), arg[0], errno);
	_exit(99);
	/*NOTREACHED*/
}
Beispiel #23
0
static void
main_loop(char *devname, boolean_t cttyflag)
{
	int		fd, fb, i;
	char		*user = NULL;		/* authorized user */
	char		*pass;			/* password from user */
	char		*cpass;			/* crypted password */
	struct spwd	spwd;
	struct spwd	*lshpw;			/* local shadow */
	char		shadow[NSS_BUFLEN_SHADOW];
	FILE		*sysmsgfd;

	for (i = 0; i < 3; i++)
		(void) close(i);
	if (cttyflag == B_FALSE) {
		if (setsid() == -1)
			exit(EXIT_FAILURE);
	}
	if ((fd = open(devname, O_RDWR)) < 0)
		exit(EXIT_FAILURE);

	/*
	 * In system maintenance mode, all virtual console instances
	 * of the svc:/system/console-login service are not available
	 * any more, and only the system console is available. So here
	 * we always switch to the system console in case at the moment
	 * the active console isn't it.
	 */
	(void) ioctl(fd, VT_ACTIVATE, 1);

	if (fd != 0)
		(void) dup2(fd, STDIN_FILENO);
	if (fd != 1)
		(void) dup2(fd, STDOUT_FILENO);
	if (fd != 2)
		(void) dup2(fd, STDERR_FILENO);
	if (fd > 2)
		(void) close(fd);

	/* Stop progress bar and reset console mode to text */
	if ((fb = open("/dev/fb", O_RDONLY)) >= 0) {
		(void) ioctl(fb, KDSETMODE, KD_RESETTEXT);
		(void) close(fb);
	}

	sysmsgfd = fopen("/dev/sysmsg", "w");

	sanitize_tty(fileno(stdin));

	for (;;) {
		do {
			(void) printf("\nEnter user name for system "
			    "maintenance (control-d to bypass): ");
			user = sulogin_getinput(devname, ECHOON);
			if (user == NULL) {
				/* signal other children to exit */
				(void) sigsend(P_PID, masterpid, SIGUSR1);
				/* ^D, so straight to default init state */
				exit(EXIT_FAILURE);
			}
		} while (user[0] == '\0');
		(void) printf("Enter %s password (control-d to bypass): ",
		    user);

		if ((pass = sulogin_getinput(devname, ECHOOFF)) == NULL) {
			/* signal other children to exit */
			(void) sigsend(P_PID, masterpid, SIGUSR1);
			/* ^D, so straight to default init state */
			free(user);
			exit(EXIT_FAILURE);
		}
		lshpw = getspnam_r(user, &spwd, shadow, sizeof (shadow));
		if (lshpw == NULL) {
			/*
			 * the user entered doesn't exist, too bad.
			 */
			goto sorry;
		}

		/*
		 * There is a special case error to catch here:
		 * If the password is hashed with an algorithm
		 * other than the old unix crypt the call to crypt(3c)
		 * could fail if /usr is corrupt or not available
		 * since by default /etc/security/crypt.conf will
		 * have the crypt_ modules located under /usr/lib.
		 * Or it could happen if /etc/security/crypt.conf
		 * is corrupted.
		 *
		 * If this happens crypt(3c) will return NULL and
		 * set errno to ELIBACC for the former condition or
		 * EINVAL for the latter, in this case we bypass
		 * authentication and just verify that the user is
		 * authorized.
		 */

		errno = 0;
		cpass = crypt(pass, lshpw->sp_pwdp);
		if (((cpass == NULL) && (lshpw->sp_pwdp[0] == '$')) &&
		    ((errno == ELIBACC) || (errno == EINVAL))) {
			goto checkauth;
		} else if ((cpass == NULL) ||
		    (strcmp(cpass, lshpw->sp_pwdp) != 0)) {
			goto sorry;
		}

checkauth:
		/*
		 * There is a special case error here as well.
		 * If /etc/user_attr is corrupt, getusernam("root")
		 * returns NULL.
		 * In this case, we just give access because this is similar
		 * to the case of root not existing in /etc/passwd.
		 */

		if ((getusernam("root") != NULL) &&
		    (chkauthattr(MAINTENANCE_AUTH, user) != 1)) {
			goto sorry;
		}
		(void) fprintf(sysmsgfd, "\nsingle-user privilege "
		    "assigned to %s on %s.\n", user, devname);
		(void) sigsend(P_PID, masterpid, SIGUSR1);
		(void) wait(NULL);
		free(user);
		free(pass);
		single(su, devname);
		/* single never returns */

sorry:
		(void) printf("\nLogin incorrect or user %s not authorized\n",
		    user);
		free(user);
		free(pass);
		(void) sleep(sleeptime);
	}
}
Beispiel #24
0
void
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{
	uintptr *sp;
	SigTab *t;
	bool crash;

	if(sig == SIGPROF) {
		if(gp != m->g0 && gp != m->gsignal)
			runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp);
		return;
	}

	t = &runtime·sigtab[sig];
	if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
		if(gp == nil || gp == m->g0)
			goto Throw;

		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = SIG_CODE0(info, ctxt);
		gp->sigcode1 = SIG_CODE1(info, ctxt);
		gp->sigpc = SIG_RIP(info, ctxt);

#ifdef GOOS_darwin
		// Work around Leopard bug that doesn't set FPE_INTDIV.
		// Look at instruction to see if it is a divide.
		// Not necessary in Snow Leopard (si_code will be != 0).
		if(sig == SIGFPE && gp->sigcode0 == 0) {
			byte *pc;
			pc = (byte*)gp->sigpc;
			if((pc[0]&0xF0) == 0x40)	// 64-bit REX prefix
				pc++;
			else if(pc[0] == 0x66)	// 16-bit instruction prefix
				pc++;
			if(pc[0] == 0xF6 || pc[0] == 0xF7)
				gp->sigcode0 = FPE_INTDIV;
		}
#endif

		// Only push runtime·sigpanic if rip != 0.
		// If rip == 0, probably panicked because of a
		// call to a nil func.  Not pushing that onto sp will
		// make the trace look like a call to runtime·sigpanic instead.
		// (Otherwise the trace will end at runtime·sigpanic and we
		// won't get to see who faulted.)
		if(SIG_RIP(info, ctxt) != 0) {
			sp = (uintptr*)SIG_RSP(info, ctxt);
			*--sp = SIG_RIP(info, ctxt);
			SIG_RSP(info, ctxt) = (uintptr)sp;
		}
		SIG_RIP(info, ctxt) = (uintptr)runtime·sigpanic;
		return;
	}

	if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
		if(runtime·sigsend(sig))
			return;
	if(t->flags & SigKill)
		runtime·exit(2);
	if(!(t->flags & SigThrow))
		return;

Throw:
	m->throwing = 1;
	m->caughtsig = gp;
	runtime·startpanic();

	if(sig < 0 || sig >= NSIG)
		runtime·printf("Signal %d\n", sig);
	else
		runtime·printf("%s\n", runtime·sigtab[sig].name);

	runtime·printf("PC=%X\n", SIG_RIP(info, ctxt));
	if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
		runtime·printf("signal arrived during cgo execution\n");
		gp = m->lockedg;
	}
	runtime·printf("\n");

	if(runtime·gotraceback(&crash)){
		runtime·traceback(SIG_RIP(info, ctxt), SIG_RSP(info, ctxt), 0, gp);
		runtime·tracebackothers(gp);
		runtime·printf("\n");
		runtime·dumpregs(info, ctxt);
	}
	
	if(crash)
		runtime·crash();

	runtime·exit(2);
}
Beispiel #25
0
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
	Ucontext *uc;
	Mcontext *mc;
	Sigcontext *r;
	uintptr *sp;

	uc = context;
	mc = &uc->uc_mcontext;
	r = (Sigcontext*)mc;	// same layout, more conveient names

	if(sig == SIGPROF) {
		runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
		return;
	}

	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = info->si_code;
		gp->sigcode1 = ((uintptr*)info)[2];
		gp->sigpc = r->rip;

		// Only push runtime·sigpanic if r->rip != 0.
		// If r->rip == 0, probably panicked because of a
		// call to a nil func.  Not pushing that onto sp will
		// make the trace look like a call to runtime·sigpanic instead.
		// (Otherwise the trace will end at runtime·sigpanic and we
		// won't get to see who faulted.)
		if(r->rip != 0) {
			sp = (uintptr*)r->rsp;
			*--sp = r->rip;
			r->rsp = (uintptr)sp;
		}
		r->rip = (uintptr)runtime·sigpanic;
		return;
	}

	if(runtime·sigtab[sig].flags & SigQueue) {
		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
			return;
		runtime·exit(2);	// SIGINT, SIGTERM, etc
	}

	if(runtime·panicking)	// traceback already printed
		runtime·exit(2);
	runtime·panicking = 1;

	if(sig < 0 || sig >= NSIG)
		runtime·printf("Signal %d\n", sig);
	else
		runtime·printf("%s\n", runtime·sigtab[sig].name);

	runtime·printf("PC=%X\n", r->rip);
	runtime·printf("\n");

	if(runtime·gotraceback()){
		runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
		runtime·tracebackothers(gp);
		runtime·dumpregs(r);
	}

	runtime·exit(2);
}
Beispiel #26
0
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
	Ucontext *uc;
	Mcontext32 *mc;
	Regs32 *r;
	uintptr *sp;
	byte *pc;
	SigTab *t;

	uc = context;
	mc = uc->uc_mcontext;
	r = &mc->ss;

	if(sig == SIGPROF) {
		if(gp != m->g0 && gp != m->gsignal)
			runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
		return;
	}

	t = &runtime·sigtab[sig];
	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
		if(gp == nil || gp == m->g0)
			goto Throw;
		// Work around Leopard bug that doesn't set FPE_INTDIV.
		// Look at instruction to see if it is a divide.
		// Not necessary in Snow Leopard (si_code will be != 0).
		if(sig == SIGFPE && info->si_code == 0) {
			pc = (byte*)r->eip;
			if(pc[0] == 0x66)	// 16-bit instruction prefix
				pc++;
			if(pc[0] == 0xF6 || pc[0] == 0xF7)
				info->si_code = FPE_INTDIV;
		}

		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = info->si_code;
		gp->sigcode1 = (uintptr)info->si_addr;
		gp->sigpc = r->eip;

		// Only push runtime·sigpanic if r->eip != 0.
		// If r->eip == 0, probably panicked because of a
		// call to a nil func.  Not pushing that onto sp will
		// make the trace look like a call to runtime·sigpanic instead.
		// (Otherwise the trace will end at runtime·sigpanic and we
		// won't get to see who faulted.)
		if(r->eip != 0) {
			sp = (uintptr*)r->esp;
			*--sp = r->eip;
			r->esp = (uintptr)sp;
		}
		r->eip = (uintptr)runtime·sigpanic;
		return;
	}

	if(info->si_code == SI_USER || (t->flags & SigNotify))
		if(runtime·sigsend(sig))
			return;
	if(t->flags & SigKill)
		runtime·exit(2);
	if(!(t->flags & SigThrow))
		return;

Throw:
	runtime·startpanic();

	if(sig < 0 || sig >= NSIG){
		runtime·printf("Signal %d\n", sig);
	}else{
		runtime·printf("%s\n", runtime·sigtab[sig].name);
	}

	runtime·printf("PC=%x\n", r->eip);
	if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
		runtime·printf("signal arrived during cgo execution\n");
		gp = m->lockedg;
	}	
	runtime·printf("\n");

	if(runtime·gotraceback()){
		runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
		runtime·tracebackothers(gp);
		runtime·dumpregs(r);
	}

	runtime·exit(2);
}
Beispiel #27
0
void
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{
	uintptr *sp;
	SigTab *t;
	bool crash;

	if(sig == SIGPROF) {
		runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp, g->m);
		return;
	}

#ifdef GOOS_darwin
	// x86-64 has 48-bit virtual addresses. The top 16 bits must echo bit 47.
	// The hardware delivers a different kind of fault for a malformed address
	// than it does for an attempt to access a valid but unmapped address.
	// OS X 10.9.2 mishandles the malformed address case, making it look like
	// a user-generated signal (like someone ran kill -SEGV ourpid).
	// We pass user-generated signals to os/signal, or else ignore them.
	// Doing that here - and returning to the faulting code - results in an
	// infinite loop. It appears the best we can do is rewrite what the kernel
	// delivers into something more like the truth. The address used below
	// has very little chance of being the one that caused the fault, but it is
	// malformed, it is clearly not a real pointer, and if it does get printed
	// in real life, people will probably search for it and find this code.
	// There are no Google hits for b01dfacedebac1e or 0xb01dfacedebac1e
	// as I type this comment.
	if(sig == SIGSEGV && SIG_CODE0(info, ctxt) == SI_USER) {
		SIG_CODE0(info, ctxt) = SI_USER+1;
		info->si_addr = (void*)(uintptr)0xb01dfacedebac1eULL;
	}
#endif

	t = &runtime·sigtab[sig];
	if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = SIG_CODE0(info, ctxt);
		gp->sigcode1 = SIG_CODE1(info, ctxt);
		gp->sigpc = SIG_RIP(info, ctxt);

#ifdef GOOS_darwin
		// Work around Leopard bug that doesn't set FPE_INTDIV.
		// Look at instruction to see if it is a divide.
		// Not necessary in Snow Leopard (si_code will be != 0).
		if(sig == SIGFPE && gp->sigcode0 == 0) {
			byte *pc;
			pc = (byte*)gp->sigpc;
			if((pc[0]&0xF0) == 0x40)	// 64-bit REX prefix
				pc++;
			else if(pc[0] == 0x66)	// 16-bit instruction prefix
				pc++;
			if(pc[0] == 0xF6 || pc[0] == 0xF7)
				gp->sigcode0 = FPE_INTDIV;
		}
#endif

		// Only push runtime·sigpanic if rip != 0.
		// If rip == 0, probably panicked because of a
		// call to a nil func.  Not pushing that onto sp will
		// make the trace look like a call to runtime·sigpanic instead.
		// (Otherwise the trace will end at runtime·sigpanic and we
		// won't get to see who faulted.)
		if(SIG_RIP(info, ctxt) != 0) {
			sp = (uintptr*)SIG_RSP(info, ctxt);
			if(sizeof(uintreg) > sizeof(uintptr))
				*--sp = 0;
			*--sp = SIG_RIP(info, ctxt);
			SIG_RSP(info, ctxt) = (uintptr)sp;
		}
		SIG_RIP(info, ctxt) = (uintptr)runtime·sigpanic;
		return;
	}

	if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
		if(runtime·sigsend(sig))
			return;
	if(t->flags & SigKill)
		runtime·exit(2);
	if(!(t->flags & SigThrow))
		return;

	g->m->throwing = 1;
	g->m->caughtsig = gp;
	runtime·startpanic();

	if(sig < 0 || sig >= NSIG)
		runtime·printf("Signal %d\n", sig);
	else
		runtime·printf("%s\n", runtime·sigtab[sig].name);

	runtime·printf("PC=%X\n", SIG_RIP(info, ctxt));
	if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
		runtime·printf("signal arrived during cgo execution\n");
		gp = g->m->lockedg;
	}
	runtime·printf("\n");

	if(runtime·gotraceback(&crash)){
		runtime·goroutineheader(gp);
		runtime·traceback(SIG_RIP(info, ctxt), SIG_RSP(info, ctxt), 0, gp);
		runtime·tracebackothers(gp);
		runtime·printf("\n");
		runtime·dumpregs(info, ctxt);
	}
	
	if(crash)
		runtime·crash();

	runtime·exit(2);
}
Beispiel #28
0
void
sighandler(int32 sig, Siginfo* info, void* context)
{
	Ucontext *uc;
	Mcontext *r;
	G *gp;
	uintptr *sp;

	uc = context;
	r = &uc->uc_mcontext;

	if((gp = m->curg) != nil && (sigtab[sig].flags & SigPanic)) {
		// Make it look like a call to the signal func.
		// Have to pass arguments out of band since
		// augmenting the stack frame would break
		// the unwinding code.
		gp->sig = sig;
		gp->sigcode0 = info->si_code;
		gp->sigcode1 = (uintptr)info->si_addr;

		// Only push sigpanic if r->mc_rip != 0.
		// If r->mc_rip == 0, probably panicked because of a
		// call to a nil func.  Not pushing that onto sp will
		// make the trace look like a call to sigpanic instead.
		// (Otherwise the trace will end at sigpanic and we
		// won't get to see who faulted.)
		if(r->mc_rip != 0) {
			sp = (uintptr*)r->mc_rsp;
			*--sp = r->mc_rip;
			r->mc_rsp = (uintptr)sp;
		}
		r->mc_rip = (uintptr)sigpanic;
		return;
	}

	if(sigtab[sig].flags & SigQueue) {
		if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
			return;
		exit(2);	// SIGINT, SIGTERM, etc
	}

	if(panicking)	// traceback already printed
		exit(2);
	panicking = 1;

	if(sig < 0 || sig >= NSIG)
		printf("Signal %d\n", sig);
	else
		printf("%s\n", sigtab[sig].name);

	printf("PC=%X\n", r->mc_rip);
	printf("\n");

	if(gotraceback()){
		traceback((void*)r->mc_rip, (void*)r->mc_rsp, 0, (void*)r->mc_r15);
		tracebackothers((void*)r->mc_r15);
		dumpregs(r);
	}

	breakpoint();
	exit(2);
}