Beispiel #1
0
/*
 * This creates a new process as a copy of the old one,
 * but does not actually start it yet.
 *
 * It copies the registers, and all the appropriate
 * parts of the process environment (as per the clone
 * flags). The actual kick-off is left to the caller.
 */
static task_t *copy_process(unsigned long clone_flags,
				 unsigned long stack_start,
				 struct pt_regs *regs,
				 unsigned long stack_size,
				 int __user *parent_tidptr,
				 int __user *child_tidptr,
				 int pid)
{
	int retval;
	struct task_struct *p = NULL;

	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
		return ERR_PTR(-EINVAL);

	/*
	 * Thread groups must share signals as well, and detached threads
	 * can only be started up within the thread group.
	 */
	if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
		return ERR_PTR(-EINVAL);

	/*
	 * Shared signal handlers imply shared VM. By way of the above,
	 * thread groups also imply shared VM. Blocking this case allows
	 * for various simplifications in other code.
	 */
	if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
		return ERR_PTR(-EINVAL);

	retval = security_task_create(clone_flags);
	if (retval)
		goto fork_out;

	retval = -ENOMEM;
	p = dup_task_struct(current);
	if (!p)
		goto fork_out;

	retval = -EAGAIN;
	if (atomic_read(&p->user->processes) >=
			p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
				p->user != &root_user)
			goto bad_fork_free;
	}

	atomic_inc(&p->user->__count);
	atomic_inc(&p->user->processes);
	get_group_info(p->group_info);

	/*
	 * If multiple threads are within copy_process(), then this check
	 * triggers too late. This doesn't hurt, the check is only there
	 * to stop root fork bombs.
	 */
	if (nr_threads >= max_threads)
		goto bad_fork_cleanup_count;

	if (!try_module_get(p->thread_info->exec_domain->module))
		goto bad_fork_cleanup_count;

	if (p->binfmt && !try_module_get(p->binfmt->module))
		goto bad_fork_cleanup_put_domain;

	p->did_exec = 0;
	copy_flags(clone_flags, p);
	p->pid = pid;
	retval = -EFAULT;
	if (clone_flags & CLONE_PARENT_SETTID)
		if (put_user(p->pid, parent_tidptr))
			goto bad_fork_cleanup;

	p->proc_dentry = NULL;

	INIT_LIST_HEAD(&p->children);
	INIT_LIST_HEAD(&p->sibling);
	p->vfork_done = NULL;
	spin_lock_init(&p->alloc_lock);
	spin_lock_init(&p->proc_lock);

	clear_tsk_thread_flag(p, TIF_SIGPENDING);
	init_sigpending(&p->pending);

	p->utime = cputime_zero;
	p->stime = cputime_zero;
 	p->sched_time = 0;
	p->rchar = 0;		/* I/O counter: bytes read */
	p->wchar = 0;		/* I/O counter: bytes written */
	p->syscr = 0;		/* I/O counter: read syscalls */
	p->syscw = 0;		/* I/O counter: write syscalls */
	acct_clear_integrals(p);

 	p->it_virt_expires = cputime_zero;
	p->it_prof_expires = cputime_zero;
 	p->it_sched_expires = 0;
 	INIT_LIST_HEAD(&p->cpu_timers[0]);
 	INIT_LIST_HEAD(&p->cpu_timers[1]);
 	INIT_LIST_HEAD(&p->cpu_timers[2]);

	p->lock_depth = -1;		/* -1 = no lock */
	do_posix_clock_monotonic_gettime(&p->start_time);
	p->security = NULL;
	p->io_context = NULL;
	p->io_wait = NULL;
	p->audit_context = NULL;
#ifdef CONFIG_NUMA
 	p->mempolicy = mpol_copy(p->mempolicy);
 	if (IS_ERR(p->mempolicy)) {
 		retval = PTR_ERR(p->mempolicy);
 		p->mempolicy = NULL;
 		goto bad_fork_cleanup;
 	}
#endif

	p->tgid = p->pid;
	if (clone_flags & CLONE_THREAD)
		p->tgid = current->tgid;

	if ((retval = security_task_alloc(p)))
		goto bad_fork_cleanup_policy;
	if ((retval = audit_alloc(p)))
		goto bad_fork_cleanup_security;
	/* copy all the process information */
	if ((retval = copy_semundo(clone_flags, p)))
		goto bad_fork_cleanup_audit;
	if ((retval = copy_files(clone_flags, p)))
		goto bad_fork_cleanup_semundo;
	if ((retval = copy_fs(clone_flags, p)))
		goto bad_fork_cleanup_files;
	if ((retval = copy_sighand(clone_flags, p)))
		goto bad_fork_cleanup_fs;
	if ((retval = copy_signal(clone_flags, p)))
		goto bad_fork_cleanup_sighand;
	if ((retval = copy_mm(clone_flags, p)))
		goto bad_fork_cleanup_signal;
	if ((retval = copy_keys(clone_flags, p)))
		goto bad_fork_cleanup_mm;
	if ((retval = copy_namespace(clone_flags, p)))
		goto bad_fork_cleanup_keys;
	retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
	if (retval)
		goto bad_fork_cleanup_namespace;

	p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
	/*
	 * Clear TID on mm_release()?
	 */
	p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;

	/*
	 * Syscall tracing should be turned off in the child regardless
	 * of CLONE_PTRACE.
	 */
	clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);

	/* Our parent execution domain becomes current domain
	   These must match for thread signalling to apply */
	   
	p->parent_exec_id = p->self_exec_id;

	/* ok, now we should be set up.. */
	p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL);
	p->pdeath_signal = 0;
	p->exit_state = 0;

	/* Perform scheduler related setup */
	sched_fork(p);

	/*
	 * Ok, make it visible to the rest of the system.
	 * We dont wake it up yet.
	 */
	p->group_leader = p;
	INIT_LIST_HEAD(&p->ptrace_children);
	INIT_LIST_HEAD(&p->ptrace_list);

	/* Need tasklist lock for parent etc handling! */
	write_lock_irq(&tasklist_lock);

	/*
	 * The task hasn't been attached yet, so cpus_allowed mask cannot
	 * have changed. The cpus_allowed mask of the parent may have
	 * changed after it was copied first time, and it may then move to
	 * another CPU - so we re-copy it here and set the child's CPU to
	 * the parent's CPU. This avoids alot of nasty races.
	 */
	p->cpus_allowed = current->cpus_allowed;
	set_task_cpu(p, smp_processor_id());

	/*
	 * Check for pending SIGKILL! The new thread should not be allowed
	 * to slip out of an OOM kill. (or normal SIGKILL.)
	 */
	if (sigismember(&current->pending.signal, SIGKILL)) {
		write_unlock_irq(&tasklist_lock);
		retval = -EINTR;
		goto bad_fork_cleanup_namespace;
	}

	/* CLONE_PARENT re-uses the old parent */
	if (clone_flags & (CLONE_PARENT|CLONE_THREAD))
		p->real_parent = current->real_parent;
	else
		p->real_parent = current;
	p->parent = p->real_parent;

	if (clone_flags & CLONE_THREAD) {
		spin_lock(&current->sighand->siglock);
		/*
		 * Important: if an exit-all has been started then
		 * do not create this new thread - the whole thread
		 * group is supposed to exit anyway.
		 */
		if (current->signal->flags & SIGNAL_GROUP_EXIT) {
			spin_unlock(&current->sighand->siglock);
			write_unlock_irq(&tasklist_lock);
			retval = -EAGAIN;
			goto bad_fork_cleanup_namespace;
		}
		p->group_leader = current->group_leader;

		if (current->signal->group_stop_count > 0) {
			/*
			 * There is an all-stop in progress for the group.
			 * We ourselves will stop as soon as we check signals.
			 * Make the new thread part of that group stop too.
			 */
			current->signal->group_stop_count++;
			set_tsk_thread_flag(p, TIF_SIGPENDING);
		}

		if (!cputime_eq(current->signal->it_virt_expires,
				cputime_zero) ||
		    !cputime_eq(current->signal->it_prof_expires,
				cputime_zero) ||
		    current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY ||
		    !list_empty(&current->signal->cpu_timers[0]) ||
		    !list_empty(&current->signal->cpu_timers[1]) ||
		    !list_empty(&current->signal->cpu_timers[2])) {
			/*
			 * Have child wake up on its first tick to check
			 * for process CPU timers.
			 */
			p->it_prof_expires = jiffies_to_cputime(1);
		}

		spin_unlock(&current->sighand->siglock);
	}

	SET_LINKS(p);
	if (unlikely(p->ptrace & PT_PTRACED))
		__ptrace_link(p, current->parent);

	cpuset_fork(p);

	attach_pid(p, PIDTYPE_PID, p->pid);
	attach_pid(p, PIDTYPE_TGID, p->tgid);
	if (thread_group_leader(p)) {
		attach_pid(p, PIDTYPE_PGID, process_group(p));
		attach_pid(p, PIDTYPE_SID, p->signal->session);
		if (p->pid)
			__get_cpu_var(process_counts)++;
	}

	nr_threads++;
	total_forks++;
	write_unlock_irq(&tasklist_lock);
	retval = 0;

fork_out:
	if (retval)
		return ERR_PTR(retval);
	return p;

bad_fork_cleanup_namespace:
	exit_namespace(p);
bad_fork_cleanup_keys:
	exit_keys(p);
bad_fork_cleanup_mm:
	if (p->mm)
		mmput(p->mm);
bad_fork_cleanup_signal:
	exit_signal(p);
bad_fork_cleanup_sighand:
	exit_sighand(p);
bad_fork_cleanup_fs:
	exit_fs(p); /* blocking */
bad_fork_cleanup_files:
	exit_files(p); /* blocking */
bad_fork_cleanup_semundo:
	exit_sem(p);
bad_fork_cleanup_audit:
	audit_free(p);
bad_fork_cleanup_security:
	security_task_free(p);
bad_fork_cleanup_policy:
#ifdef CONFIG_NUMA
	mpol_free(p->mempolicy);
#endif
bad_fork_cleanup:
	if (p->binfmt)
		module_put(p->binfmt->module);
bad_fork_cleanup_put_domain:
	module_put(p->thread_info->exec_domain->module);
bad_fork_cleanup_count:
	put_group_info(p->group_info);
	atomic_dec(&p->user->processes);
	free_uid(p->user);
bad_fork_free:
	free_task(p);
	goto fork_out;
}
Beispiel #2
0
static void
tstp(int dummy GCC_UNUSED)
{
    sigset_t mask, omask;
    sigaction_t act, oact;

#ifdef SIGTTOU
    int sigttou_blocked;
#endif

    T(("tstp() called"));

    /*
     * The user may have changed the prog_mode tty bits, so save them.
     *
     * But first try to detect whether we still are in the foreground
     * process group - if not, an interactive shell may already have
     * taken ownership of the tty and modified the settings when our
     * parent was stopped before us, and we would likely pick up the
     * settings already modified by the shell.
     */
    if (SP != 0 && !SP->_endwin)	/* don't do this if we're not in curses */
#if HAVE_TCGETPGRP
	if (tcgetpgrp(STDIN_FILENO) == getpgrp())
#endif
	    def_prog_mode();

    /*
     * Block window change and timer signals.  The latter
     * is because applications use timers to decide when
     * to repaint the screen.
     */
    (void) sigemptyset(&mask);
    (void) sigaddset(&mask, SIGALRM);
#if USE_SIGWINCH
    (void) sigaddset(&mask, SIGWINCH);
#endif
    (void) sigprocmask(SIG_BLOCK, &mask, &omask);

#ifdef SIGTTOU
    sigttou_blocked = sigismember(&omask, SIGTTOU);
    if (!sigttou_blocked) {
	(void) sigemptyset(&mask);
	(void) sigaddset(&mask, SIGTTOU);
	(void) sigprocmask(SIG_BLOCK, &mask, NULL);
    }
#endif

    /*
     * End window mode, which also resets the terminal state to the
     * original (pre-curses) modes.
     */
    endwin();

    /* Unblock SIGTSTP. */
    (void) sigemptyset(&mask);
    (void) sigaddset(&mask, SIGTSTP);
#ifdef SIGTTOU
    if (!sigttou_blocked) {
	/* Unblock this too if it wasn't blocked on entry */
	(void) sigaddset(&mask, SIGTTOU);
    }
#endif
    (void) sigprocmask(SIG_UNBLOCK, &mask, NULL);

    /* Now we want to resend SIGSTP to this process and suspend it */
    act.sa_handler = SIG_DFL;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
#ifdef SA_RESTART
    act.sa_flags |= SA_RESTART;
#endif /* SA_RESTART */
    sigaction(SIGTSTP, &act, &oact);
    kill(getpid(), SIGTSTP);

    /* Process gets suspended...time passes...process resumes */

    T(("SIGCONT received"));
    sigaction(SIGTSTP, &oact, NULL);
    flushinp();

    /*
     * If the user modified the tty state while suspended, he wants
     * those changes to stick.  So save the new "default" terminal state.
     */
    def_shell_mode();

    /*
     * This relies on the fact that doupdate() will restore the
     * program-mode tty state, and issue enter_ca_mode if need be.
     */
    doupdate();

    /* Reset the signals. */
    (void) sigprocmask(SIG_SETMASK, &omask, NULL);
}
/*
 * Look whether some events already occurred (or failed) and move
 * corresponding threads from waiting queue back to ready queue.
 */
intern void pth_sched_eventmanager(pth_time_t *now, int dopoll)
{
    pth_t nexttimer_thread;
    pth_event_t nexttimer_ev;
    pth_time_t nexttimer_value;
    pth_event_t evh;
    pth_event_t ev;
    pth_t t;
    pth_t tlast;
    int this_occurred;
    int any_occurred;
    fd_set rfds;
    fd_set wfds;
    fd_set efds;
    struct timeval delay;
    struct timeval *pdelay;
    sigset_t oss;
    struct sigaction sa;
    struct sigaction osa[1+PTH_NSIG];
    char minibuf[128];
    int loop_repeat;
    int fdmax;
    int rc;
    int sig;
    int n;

    pth_debug2("pth_sched_eventmanager: enter in %s mode",
               dopoll ? "polling" : "waiting");

    /* entry point for internal looping in event handling */
    loop_entry:
    loop_repeat = FALSE;

    /* initialize fd sets */
    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    FD_ZERO(&efds);
    fdmax = -1;

    /* initialize signal status */
    sigpending(&pth_sigpending);
    sigfillset(&pth_sigblock);
    sigemptyset(&pth_sigcatch);
    sigemptyset(&pth_sigraised);

    /* initialize next timer */
    pth_time_set(&nexttimer_value, PTH_TIME_ZERO);
    nexttimer_thread = NULL;
    nexttimer_ev = NULL;

    /* for all threads in the waiting queue... */
    any_occurred = FALSE;
    for (t = pth_pqueue_head(&pth_WQ); t != NULL;
         t = pth_pqueue_walk(&pth_WQ, t, PTH_WALK_NEXT)) {

        /* determine signals we block */
        for (sig = 1; sig < PTH_NSIG; sig++)
            if (!sigismember(&(t->mctx.sigs), sig))
                sigdelset(&pth_sigblock, sig);

        /* cancellation support */
        if (t->cancelreq == TRUE)
            any_occurred = TRUE;

        /* ... and all their events... */
        if (t->events == NULL)
            continue;
        /* ...check whether events occurred */
        ev = evh = t->events;
        do {
            if (ev->ev_status == PTH_STATUS_PENDING) {
                this_occurred = FALSE;

                /* Filedescriptor I/O */
                if (ev->ev_type == PTH_EVENT_FD) {
                    /* filedescriptors are checked later all at once.
                       Here we only assemble them in the fd sets */
                    if (ev->ev_goal & PTH_UNTIL_FD_READABLE)
                        FD_SET(ev->ev_args.FD.fd, &rfds);
                    if (ev->ev_goal & PTH_UNTIL_FD_WRITEABLE)
                        FD_SET(ev->ev_args.FD.fd, &wfds);
                    if (ev->ev_goal & PTH_UNTIL_FD_EXCEPTION)
                        FD_SET(ev->ev_args.FD.fd, &efds);
                    if (fdmax < ev->ev_args.FD.fd)
                        fdmax = ev->ev_args.FD.fd;
                }
                /* Filedescriptor Set Select I/O */
                else if (ev->ev_type == PTH_EVENT_SELECT) {
                    /* filedescriptors are checked later all at once.
                       Here we only merge the fd sets. */
                    pth_util_fds_merge(ev->ev_args.SELECT.nfd,
                                       ev->ev_args.SELECT.rfds, &rfds,
                                       ev->ev_args.SELECT.wfds, &wfds,
                                       ev->ev_args.SELECT.efds, &efds);
                    if (fdmax < ev->ev_args.SELECT.nfd-1)
                        fdmax = ev->ev_args.SELECT.nfd-1;
                }
                /* Signal Set */
                else if (ev->ev_type == PTH_EVENT_SIGS) {
                    for (sig = 1; sig < PTH_NSIG; sig++) {
                        if (sigismember(ev->ev_args.SIGS.sigs, sig)) {
                            /* thread signal handling */
                            if (sigismember(&t->sigpending, sig)) {
                                *(ev->ev_args.SIGS.sig) = sig;
                                sigdelset(&t->sigpending, sig);
                                t->sigpendcnt--;
                                this_occurred = TRUE;
                            }
                            /* process signal handling */
                            if (sigismember(&pth_sigpending, sig)) {
                                if (ev->ev_args.SIGS.sig != NULL)
                                    *(ev->ev_args.SIGS.sig) = sig;
                                pth_util_sigdelete(sig);
                                sigdelset(&pth_sigpending, sig);
                                this_occurred = TRUE;
                            }
                            else {
                                sigdelset(&pth_sigblock, sig);
                                sigaddset(&pth_sigcatch, sig);
                            }
                        }
                    }
                }
                /* Timer */
                else if (ev->ev_type == PTH_EVENT_TIME) {
                    if (pth_time_cmp(&(ev->ev_args.TIME.tv), now) < 0)
                        this_occurred = TRUE;
                    else {
                        /* remember the timer which will be elapsed next */
                        if ((nexttimer_thread == NULL && nexttimer_ev == NULL) ||
                            pth_time_cmp(&(ev->ev_args.TIME.tv), &nexttimer_value) < 0) {
                            nexttimer_thread = t;
                            nexttimer_ev = ev;
                            pth_time_set(&nexttimer_value, &(ev->ev_args.TIME.tv));
                        }
                    }
                }
                /* Message Port Arrivals */
                else if (ev->ev_type == PTH_EVENT_MSG) {
                    if (pth_ring_elements(&(ev->ev_args.MSG.mp->mp_queue)) > 0)
                        this_occurred = TRUE;
                }
                /* Mutex Release */
                else if (ev->ev_type == PTH_EVENT_MUTEX) {
                    if (!(ev->ev_args.MUTEX.mutex->mx_state & PTH_MUTEX_LOCKED))
                        this_occurred = TRUE;
                }
                /* Condition Variable Signal */
                else if (ev->ev_type == PTH_EVENT_COND) {
                    if (ev->ev_args.COND.cond->cn_state & PTH_COND_SIGNALED) {
                        if (ev->ev_args.COND.cond->cn_state & PTH_COND_BROADCAST)
                            this_occurred = TRUE;
                        else {
                            if (!(ev->ev_args.COND.cond->cn_state & PTH_COND_HANDLED)) {
                                ev->ev_args.COND.cond->cn_state |= PTH_COND_HANDLED;
                                this_occurred = TRUE;
                            }
                        }
                    }
                }
                /* Thread Termination */
                else if (ev->ev_type == PTH_EVENT_TID) {
                    if (   (   ev->ev_args.TID.tid == NULL
                            && pth_pqueue_elements(&pth_DQ) > 0)
                        || (   ev->ev_args.TID.tid != NULL
                            && ev->ev_args.TID.tid->state == ev->ev_goal))
                        this_occurred = TRUE;
                }
                /* Custom Event Function */
                else if (ev->ev_type == PTH_EVENT_FUNC) {
                    if (ev->ev_args.FUNC.func(ev->ev_args.FUNC.arg))
                        this_occurred = TRUE;
                    else {
                        pth_time_t tv;
                        pth_time_set(&tv, now);
                        pth_time_add(&tv, &(ev->ev_args.FUNC.tv));
                        if ((nexttimer_thread == NULL && nexttimer_ev == NULL) ||
                            pth_time_cmp(&tv, &nexttimer_value) < 0) {
                            nexttimer_thread = t;
                            nexttimer_ev = ev;
                            pth_time_set(&nexttimer_value, &tv);
                        }
                    }
                }

                /* tag event if it has occurred */
                if (this_occurred) {
                    pth_debug2("pth_sched_eventmanager: [non-I/O] event occurred for thread \"%s\"", t->name);
                    ev->ev_status = PTH_STATUS_OCCURRED;
                    any_occurred = TRUE;
                }
            }
        } while ((ev = ev->ev_next) != evh);
    }
    if (any_occurred)
        dopoll = TRUE;

    /* now decide how to poll for fd I/O and timers */
    if (dopoll) {
        /* do a polling with immediate timeout,
           i.e. check the fd sets only without blocking */
        pth_time_set(&delay, PTH_TIME_ZERO);
        pdelay = &delay;
    }
    else if (nexttimer_ev != NULL) {
        /* do a polling with a timeout set to the next timer,
           i.e. wait for the fd sets or the next timer */
        pth_time_set(&delay, &nexttimer_value);
        pth_time_sub(&delay, now);
        pdelay = &delay;
    }
    else {
        /* do a polling without a timeout,
           i.e. wait for the fd sets only with blocking */
        pdelay = NULL;
    }

    /* clear pipe and let select() wait for the read-part of the pipe */
    while (pth_sc(read)(pth_sigpipe[0], minibuf, sizeof(minibuf)) > 0) ;
    FD_SET(pth_sigpipe[0], &rfds);
    if (fdmax < pth_sigpipe[0])
        fdmax = pth_sigpipe[0];

    /* replace signal actions for signals we've to catch for events */
    for (sig = 1; sig < PTH_NSIG; sig++) {
        if (sigismember(&pth_sigcatch, sig)) {
            sa.sa_handler = pth_sched_eventmanager_sighandler;
            sigfillset(&sa.sa_mask);
            sa.sa_flags = 0;
            sigaction(sig, &sa, &osa[sig]);
        }
    }

    /* allow some signals to be delivered: Either to our
       catching handler or directly to the configured
       handler for signals not catched by events */
    pth_sc(sigprocmask)(SIG_SETMASK, &pth_sigblock, &oss);

    /* now do the polling for filedescriptor I/O and timers
       WHEN THE SCHEDULER SLEEPS AT ALL, THEN HERE!! */
    rc = -1;
    if (!(dopoll && fdmax == -1))
        while ((rc = pth_sc(select)(fdmax+1, &rfds, &wfds, &efds, pdelay)) < 0
               && errno == EINTR) ;

    /* restore signal mask and actions and handle signals */
    pth_sc(sigprocmask)(SIG_SETMASK, &oss, NULL);
    for (sig = 1; sig < PTH_NSIG; sig++)
        if (sigismember(&pth_sigcatch, sig))
            sigaction(sig, &osa[sig], NULL);

    /* if the timer elapsed, handle it */
    if (!dopoll && rc == 0 && nexttimer_ev != NULL) {
        if (nexttimer_ev->ev_type == PTH_EVENT_FUNC) {
            /* it was an implicit timer event for a function event,
               so repeat the event handling for rechecking the function */
            loop_repeat = TRUE;
        }
        else {
            /* it was an explicit timer event, standing for its own */
            pth_debug2("pth_sched_eventmanager: [timeout] event occurred for thread \"%s\"",
                       nexttimer_thread->name);
            nexttimer_ev->ev_status = PTH_STATUS_OCCURRED;
        }
    }

    /* if the internal signal pipe was used, adjust the select() results */
    if (!dopoll && rc > 0 && FD_ISSET(pth_sigpipe[0], &rfds)) {
        FD_CLR(pth_sigpipe[0], &rfds);
        rc--;
    }

    /* if an error occurred, avoid confusion in the cleanup loop */
    if (rc <= 0) {
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        FD_ZERO(&efds);
    }

    /* now comes the final cleanup loop where we've to
       do two jobs: first we've to do the late handling of the fd I/O events and
       additionally if a thread has one occurred event, we move it from the
       waiting queue to the ready queue */

    /* for all threads in the waiting queue... */
    t = pth_pqueue_head(&pth_WQ);
    while (t != NULL) {

        /* do the late handling of the fd I/O and signal
           events in the waiting event ring */
        any_occurred = FALSE;
        if (t->events != NULL) {
            ev = evh = t->events;
            do {
                /*
                 * Late handling for still not occured events
                 */
                if (ev->ev_status == PTH_STATUS_PENDING) {
                    /* Filedescriptor I/O */
                    if (ev->ev_type == PTH_EVENT_FD) {
                        if (   (   ev->ev_goal & PTH_UNTIL_FD_READABLE
                                && FD_ISSET(ev->ev_args.FD.fd, &rfds))
                            || (   ev->ev_goal & PTH_UNTIL_FD_WRITEABLE
                                && FD_ISSET(ev->ev_args.FD.fd, &wfds))
                            || (   ev->ev_goal & PTH_UNTIL_FD_EXCEPTION
                                && FD_ISSET(ev->ev_args.FD.fd, &efds)) ) {
                            pth_debug2("pth_sched_eventmanager: "
                                       "[I/O] event occurred for thread \"%s\"", t->name);
                            ev->ev_status = PTH_STATUS_OCCURRED;
                        }
                        else if (rc < 0) {
                            /* re-check particular filedescriptor */
                            int rc2;
                            if (ev->ev_goal & PTH_UNTIL_FD_READABLE)
                                FD_SET(ev->ev_args.FD.fd, &rfds);
                            if (ev->ev_goal & PTH_UNTIL_FD_WRITEABLE)
                                FD_SET(ev->ev_args.FD.fd, &wfds);
                            if (ev->ev_goal & PTH_UNTIL_FD_EXCEPTION)
                                FD_SET(ev->ev_args.FD.fd, &efds);
                            pth_time_set(&delay, PTH_TIME_ZERO);
                            while ((rc2 = pth_sc(select)(ev->ev_args.FD.fd+1, &rfds, &wfds, &efds, &delay)) < 0
                                   && errno == EINTR) ;
                            if (rc2 > 0) {
                                /* cleanup afterwards for next iteration */
                                FD_CLR(ev->ev_args.FD.fd, &rfds);
                                FD_CLR(ev->ev_args.FD.fd, &wfds);
                                FD_CLR(ev->ev_args.FD.fd, &efds);
                            } else if (rc2 < 0) {
                                /* cleanup afterwards for next iteration */
                                FD_ZERO(&rfds);
                                FD_ZERO(&wfds);
                                FD_ZERO(&efds);
                                ev->ev_status = PTH_STATUS_FAILED;
                                pth_debug2("pth_sched_eventmanager: "
                                           "[I/O] event failed for thread \"%s\"", t->name);
                            }
                        }
                    }
                    /* Filedescriptor Set I/O */
                    else if (ev->ev_type == PTH_EVENT_SELECT) {
                        if (pth_util_fds_test(ev->ev_args.SELECT.nfd,
                                              ev->ev_args.SELECT.rfds, &rfds,
                                              ev->ev_args.SELECT.wfds, &wfds,
                                              ev->ev_args.SELECT.efds, &efds)) {
                            n = pth_util_fds_select(ev->ev_args.SELECT.nfd,
                                                    ev->ev_args.SELECT.rfds, &rfds,
                                                    ev->ev_args.SELECT.wfds, &wfds,
                                                    ev->ev_args.SELECT.efds, &efds);
                            if (ev->ev_args.SELECT.n != NULL)
                                *(ev->ev_args.SELECT.n) = n;
                            ev->ev_status = PTH_STATUS_OCCURRED;
                            pth_debug2("pth_sched_eventmanager: "
                                       "[I/O] event occurred for thread \"%s\"", t->name);
                        }
                        else if (rc < 0) {
                            /* re-check particular filedescriptor set */
                            int rc2;
                            fd_set *prfds = NULL;
                            fd_set *pwfds = NULL;
                            fd_set *pefds = NULL;
                            fd_set trfds;
                            fd_set twfds;
                            fd_set tefds;
                            if (ev->ev_args.SELECT.rfds) {
                                memcpy(&trfds, ev->ev_args.SELECT.rfds, sizeof(rfds));
                                prfds = &trfds;
                            }
                            if (ev->ev_args.SELECT.wfds) {
                                memcpy(&twfds, ev->ev_args.SELECT.wfds, sizeof(wfds));
                                pwfds = &twfds;
                            }
                            if (ev->ev_args.SELECT.efds) {
                                memcpy(&tefds, ev->ev_args.SELECT.efds, sizeof(efds));
                                pefds = &tefds;
                            }
                            pth_time_set(&delay, PTH_TIME_ZERO);
                            while ((rc2 = pth_sc(select)(ev->ev_args.SELECT.nfd+1, prfds, pwfds, pefds, &delay)) < 0
                                   && errno == EINTR) ;
                            if (rc2 < 0) {
                                ev->ev_status = PTH_STATUS_FAILED;
                                pth_debug2("pth_sched_eventmanager: "
                                           "[I/O] event failed for thread \"%s\"", t->name);
                            }
                        }
                    }
                    /* Signal Set */
                    else if (ev->ev_type == PTH_EVENT_SIGS) {
                        for (sig = 1; sig < PTH_NSIG; sig++) {
                            if (sigismember(ev->ev_args.SIGS.sigs, sig)) {
                                if (sigismember(&pth_sigraised, sig)) {
                                    if (ev->ev_args.SIGS.sig != NULL)
                                        *(ev->ev_args.SIGS.sig) = sig;
                                    pth_debug2("pth_sched_eventmanager: "
                                               "[signal] event occurred for thread \"%s\"", t->name);
                                    sigdelset(&pth_sigraised, sig);
                                    ev->ev_status = PTH_STATUS_OCCURRED;
                                }
                            }
                        }
                    }
                }
                /*
                 * post-processing for already occured events
                 */
                else {
                    /* Condition Variable Signal */
                    if (ev->ev_type == PTH_EVENT_COND) {
                        /* clean signal */
                        if (ev->ev_args.COND.cond->cn_state & PTH_COND_SIGNALED) {
                            ev->ev_args.COND.cond->cn_state &= ~(PTH_COND_SIGNALED);
                            ev->ev_args.COND.cond->cn_state &= ~(PTH_COND_BROADCAST);
                            ev->ev_args.COND.cond->cn_state &= ~(PTH_COND_HANDLED);
                        }
                    }
                }

                /* local to global mapping */
                if (ev->ev_status != PTH_STATUS_PENDING)
                    any_occurred = TRUE;
            } while ((ev = ev->ev_next) != evh);
        }

        /* cancellation support */
        if (t->cancelreq == TRUE) {
            pth_debug2("pth_sched_eventmanager: cancellation request pending for thread \"%s\"", t->name);
            any_occurred = TRUE;
        }

        /* walk to next thread in waiting queue */
        tlast = t;
        t = pth_pqueue_walk(&pth_WQ, t, PTH_WALK_NEXT);

        /*
         * move last thread to ready queue if any events occurred for it.
         * we insert it with a slightly increased queue priority to it a
         * better chance to immediately get scheduled, else the last running
         * thread might immediately get again the CPU which is usually not
         * what we want, because we oven use pth_yield() calls to give others
         * a chance.
         */
        if (any_occurred) {
            pth_pqueue_delete(&pth_WQ, tlast);
            tlast->state = PTH_STATE_READY;
            pth_pqueue_insert(&pth_RQ, tlast->prio+1, tlast);
            pth_debug2("pth_sched_eventmanager: thread \"%s\" moved from waiting "
                       "to ready queue", tlast->name);
        }
    }

    /* perhaps we have to internally loop... */
    if (loop_repeat) {
        pth_time_set(now, PTH_TIME_NOW);
        goto loop_entry;
    }

    pth_debug1("pth_sched_eventmanager: leaving");
    return;
}
Beispiel #4
0
static void *
softsig_thread(void *arg)
{
    sigset_t ss, os;
    int i;

    sigemptyset(&ss);
    /* get the list of signals _not_ blocked by AFS_SIGSET_CLEAR() */
    pthread_sigmask(SIG_BLOCK, &ss, &os);
    pthread_sigmask(SIG_SETMASK, &os, NULL);
    sigaddset(&ss, SIGUSR1);
#if defined(AFS_DARWIN_ENV) || (defined(AFS_NBSD_ENV) && !defined(AFS_NBSD50_ENV))
    pthread_sigmask (SIG_BLOCK, &ss, NULL);
    sigdelset (&os, SIGUSR1);
#elif !defined(AFS_HPUX_ENV)
    /* On HPUX, don't wait for 'critical' signals, as things such as
     * SEGV won't cause a core, then. Some non-HPUX platforms may need
     * this, though, since apparently if we wait on some signals but not
     * e.g. SEGV, the softsig thread will still wait around when the
     * other threads were killed by the SEGV. */
    for (i = 0; i < NSIG; i++) {
	if (!sigismember(&os, i) && i != SIGSTOP && i != SIGKILL) {
	    sigaddset(&ss, i);
	    softsig_sigs[i].fatal = 1;
	}
    }
#endif /* defined(AFS_DARWIN_ENV) || defined(AFS_NBSD_ENV) */

    while (1) {
	void (*h) (int);
#if !defined(AFS_DARWIN_ENV) && (!defined(AFS_NBSD_ENV) || defined(AFS_NBSD50_ENV))
	int sigw;
#endif

	h = NULL;

	for (i = 0; i < NSIG; i++) {
	    if (softsig_sigs[i].handler && !softsig_sigs[i].inited) {
		sigaddset(&ss, i);
#if defined(AFS_DARWIN_ENV) || (defined(AFS_NBSD_ENV) && !defined(AFS_NBSD50_ENV))
		pthread_sigmask (SIG_BLOCK, &ss, NULL);
		sigdelset (&os, i);
#endif /* defined(AFS_DARWIN_ENV) || defined(AFS_NBSD_ENV) */
		softsig_sigs[i].inited = 1;
	    }
	    if (softsig_sigs[i].pending) {
		softsig_sigs[i].pending = 0;
		h = softsig_sigs[i].handler;
		break;
	    }
	}
	if (i == NSIG) {
#if defined(AFS_DARWIN_ENV) || (defined(AFS_NBSD_ENV) && !defined(AFS_NBSD50_ENV))
	    sigsuspend (&os);
#else /* !defined(AFS_DARWIN_ENV) && !defined(AFS_NBSD_ENV) */
	    sigwait(&ss, &sigw);
	    if (sigw != SIGUSR1) {
		if (softsig_sigs[sigw].fatal)
		    exit(0);
		softsig_sigs[sigw].pending = 1;
	    }
#endif /* defined(AFS_DARWIN_ENV) || defined(AFS_NBSD_ENV) */
	} else if (h)
	    h(i);
    }
    return NULL;
}
Beispiel #5
0
unsigned int mysleep(unsigned int nsecs)
{
    #ifdef DEBUG
    printf("DEBUG - mysleep(%u)\n", nsecs);
    #endif

    struct sigaction newact, oldact;
    sigset_t newmask, oldmask, suspmask, blockedmask;
    int issuspend = 0;/* SIGALRM是否被阻塞 */
    int isblocked = 0;/* 是否存在未决的SIGALRM */
    unsigned int unslept, slept;
    unsigned int oldalarm;

    oldalarm = alarm(0);

    /* 保存以前的SIGALRM配置,并设置成我们需要的配置 */
    newact.sa_handler = sig_alrm;
    sigemptyset(&newact.sa_mask);
    newact.sa_flags = 0;
    sigaction(SIGALRM, &newact, &oldact);

    /* 处理以前的SIGALRM */
    /* 判断SIGALRM是否被阻塞 */
    sigprocmask(SIG_BLOCK, NULL, &oldmask);
    if (sigismember(&oldmask, SIGALRM)) {
        /* SIGALRM被阻塞 */
        issuspend = 1;
    }

    /* 判断是否存在未决的SIGALRM */
    if (sigpending(&blockedmask) < 0) {
        err_sys("sigpending error");
    }
    if (sigismember(&blockedmask, SIGALRM)) {
        /* 存在未决的SIGALRM */
        suspmask = oldmask;
        isblocked = 1;
        sigdelset(&suspmask, SIGALRM);
        sigsuspend(&suspmask);
        sigprocmask(SIG_SETMASK, &oldmask, NULL);
    }

    sigemptyset(&newmask);
    sigaddset(&newmask, SIGALRM);
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);

    #ifdef DEBUG
    printf("DEBUG - oldalarm = %u\n", oldalarm);
    #endif

    if ((oldalarm != 0) && (oldalarm < nsecs) && (issuspend == 0)) {
        /* 以前剩余的闹钟值比睡眠时间少且没有被阻塞 */
        alarm(oldalarm);
    }
    else {
        /* 以前剩余的闹钟值比睡眠时间多或者被阻塞 */
        alarm(nsecs);
    }

    suspmask = oldmask;
    sigdelset(&suspmask, SIGALRM);
    sigsuspend(&suspmask);

    unslept = alarm(0);
    sigaction(SIGALRM, &oldact, NULL);

    sigprocmask(SIG_SETMASK, &oldmask, NULL);

    /* 计算实际睡眠时间 */
    if ((oldalarm != 0) && (oldalarm < nsecs) && (issuspend == 0)) {
        /* 以前的闹钟值比睡眠时间少 */
        slept = oldalarm - unslept;
    }
    else {
        /* 以前的闹钟值比睡眠时间多 */
        slept = nsecs - unslept;
    }

    if (isblocked == 1) {
        kill(getpid(), SIGALRM);
    }
    if (slept < oldalarm) {
        /* 以前的闹钟值比实际睡眠时间多 */
        alarm(oldalarm - slept);
        return nsecs - slept;
    }
    else {
        if (oldalarm != 0) {
            kill(getpid(), SIGALRM);
        }
        return nsecs - slept;
    }
    return 0; /* 出错 */
}
Beispiel #6
0
/* The main test function. */
int main(int argc, char * argv[])
{
	int ret, status;
	pid_t child, ctl;

	sigset_t mask, pending;

	/* Initialize output */
	output_init();

	/* block SIGUSR1 and SIGUSR2 */
	ret = sigemptyset(&mask);

	if (ret != 0)
	{
		UNRESOLVED(errno, "Failed to initialize signal set");
	}

	ret = sigaddset(&mask, SIGUSR1);

	if (ret != 0)
	{
		UNRESOLVED(errno, "Failed to add SIGUSR1 to signal set");
	}

	ret = sigaddset(&mask, SIGUSR2);

	if (ret != 0)
	{
		UNRESOLVED(errno, "Failed to add SIGUSR2 to signal set");
	}

	ret = sigprocmask(SIG_BLOCK, &mask, NULL);

	if (ret != 0)
	{
		UNRESOLVED(errno, "Sigprocmask failed");
	}

	/* Make the signals pending */
	ret = kill(getpid(), SIGUSR1);

	if (ret != 0)
	{
		UNRESOLVED(errno, "failed to kill with SIGUSR1");
	}

	ret = kill(getpid(), SIGUSR2);

	if (ret != 0)
	{
		UNRESOLVED(errno, "failed to kill with SIGUSR2");
	}

	do
	{
		ret = sigpending(&pending);

		if (ret != 0)
		{
			UNRESOLVED(errno, "failed to examine pending signal set");
		}

		ret = sigismember(&pending, SIGUSR1);

		if (ret < 0)
		{
			UNRESOLVED(errno, "Unable to check signal USR1 presence");
		}

		if (ret == 1)
		{
			ret = sigismember(&pending, SIGUSR2);

			if (ret < 0)
			{
				UNRESOLVED(errno, "Unable to check signal USR2 presence");
			}
		}
	}
	while (ret != 1);

#if VERBOSE > 0

	output("SIGUSR1 and SIGUSR2 are pending, we can fork\n");

#endif

	/* Create the child */
	child = fork();

	if (child == -1)
	{
		UNRESOLVED(errno, "Failed to fork");
	}

	/* child */
	if (child == 0)
	{
		/* Examine the current blocked signal set. USR1 & USR2 shall be present */
		ret = sigprocmask(0, NULL, &mask);

		if (ret != 0)
		{
			UNRESOLVED(errno, "Sigprocmask failed in child");
		}

		ret = sigismember(&mask, SIGUSR1);

		if (ret < 0)
		{
			UNRESOLVED(errno, "Unable to check signal USR1 presence");
		}

		if (ret == 0)
		{
			FAILED("The new process does not mask SIGUSR1 as its parent");
		}

		ret = sigismember(&mask, SIGUSR2);

		if (ret < 0)
		{
			UNRESOLVED(errno, "Unable to check signal USR2 presence");
		}

		if (ret == 0)
		{
			FAILED("The new process does not mask SIGUSR2 as its parent");
		}

#if VERBOSE > 0
		output("SIGUSR1 and SIGUSR2 are blocked in child\n");

#endif

		/* Examine pending signals */
		ret = sigpending(&pending);

		if (ret != 0)
		{
			UNRESOLVED(errno, "failed to examine pending signal set in child");
		}

		ret = sigismember(&pending, SIGUSR1);

		if (ret < 0)
		{
			UNRESOLVED(errno, "Unable to check signal USR1 presence");
		}

		if (ret != 0)
		{
			FAILED("The new process was created with SIGUSR1 pending");
		}

		ret = sigismember(&pending, SIGUSR2);

		if (ret < 0)
		{
			UNRESOLVED(errno, "Unable to check signal USR2 presence");
		}

		if (ret != 0)
		{
			FAILED("The new process was created with SIGUSR2 pending");
		}

#if VERBOSE > 0
		output("SIGUSR1 and SIGUSR2 are not pending in child\n");

#endif

		/* We're done */
		exit(PTS_PASS);
	}

	/* Parent joins the child */
	ctl = waitpid(child, &status, 0);

	if (ctl != child)
	{
		UNRESOLVED(errno, "Waitpid returned the wrong PID");
	}

	if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS))
	{
		FAILED("Child exited abnormally");
	}

	/* Test passed */
#if VERBOSE > 0

	output("Test passed\n");

#endif

	PASSED;
}
Beispiel #7
0
void *pthread_entry1( void *arg)
{
    sigset_t mask;
    siginfo_t info;
    struct timespec timeout;
    int sig, sig2, err;
    
    CYG_TEST_INFO( "Thread 1 running" );

    // Should have inherited parent's signal mask
    pthread_sigmask( 0, NULL, &mask );
    CYG_TEST_CHECK( sigismember( &mask, SIGALRM),
                                 "SIGALRM mask inherited");
    CYG_TEST_CHECK( sigismember( &mask, SIGUSR1),
                                 "SIGUSR1 mask inherited");
    CYG_TEST_CHECK( sigismember( &mask, SIGUSR2),
                                 "SIGUSR2 mask inherited");
    CYG_TEST_CHECK( sigismember( &mask, SIGSEGV),
                                 "SIGSEGV mask inherited");

    // Make a full set
    sigfillset( &mask );

    // remove USR2 and ALRM signals
    sigdelset( &mask, SIGUSR2 );
    sigdelset( &mask, SIGALRM );

    // Set signal mask
    pthread_sigmask( SIG_SETMASK, &mask, NULL );
    
    // Get main thread going again
    sem_post( &sem );

    // set up timeout
    timeout.tv_sec = 10;
    timeout.tv_nsec = 0;

    CYG_TEST_INFO( "Thread1: calling sigtimedwait()");
    
    // Wait for a signal to be delivered
    sig = sigtimedwait( &mask, &info, &timeout );

    sig2 = info.si_signo;
    
    CYG_TEST_CHECK( sig == sig2, "sigtimedwait return value not equal");
    CYG_TEST_CHECK( sig == SIGUSR1, "Signal not delivered");

    while( sigusr2_called != 2 )
    {
        CYG_TEST_INFO( "Thread1: calling pause()");        
        pause();
    }

    errno = 0; // strictly correct to reset errno first

    // now wait for SIGALRM to be delivered
    CYG_TEST_INFO( "Thread1: calling pause()");            
    err = pause();
    CYG_TEST_CHECK( -1==err, "pause returned -1");
    CYG_TEST_CHECK( EINTR==errno, "errno set to EINTR");

    // generate another SIGALRM and wait for it to be delivered too
    // we need to mask it first though

    // Make a full set
    sigfillset( &mask );

    // Set signal mask
    pthread_sigmask( SIG_SETMASK, &mask, NULL );
    
    alarm(1);
    CYG_TEST_INFO( "Thread1: calling sigwait()");            
    err = sigwait( &mask, &sig);
    CYG_TEST_CHECK( 0==err, "sigwait returned -1");
    CYG_TEST_CHECK( sig==SIGALRM, "sigwait caught alarm");

    CYG_TEST_INFO( "Thread1: calling pthread_exit()");    
    pthread_exit( (void *)((int)arg+sig2) );
}
Beispiel #8
0
int main(int argc, char **argv)
{
	video_playback_setup *settings;
	 
    	sigset_t allsignals;
    	struct sigaction action;
	struct timespec req;
	int i;
	fflush(stdout);

	vj_mem_init();

	vevo_strict_init();
	
	info = veejay_malloc();
	if (!info) {
		vj_mem_threaded_stop();
		return 1;
	}
	
   	settings = (video_playback_setup *) info->settings;

	if(!check_command_line_options(argc, argv))
	{
		veejay_free(info);
		return 0;
    	}

	
   	if(info->dump)
 	{
		veejay_set_colors(0);
		vj_event_init(NULL);
		vj_effect_initialize(720,576,0);
		vj_osc_allocate(VJ_PORT+2);	
		vj_event_dump();
		vj_effect_dump();
			fprintf(stdout, "Environment variables:\n\tSDL_VIDEO_HWACCEL\t\tSet to 1 to use SDL video hardware accel (default=on)\n\tVEEJAY_PERFORMANCE\t\tSet to \"quality\" or \"fastest\" (default is fastest)\n\tVEEJAY_AUTO_SCALE_PIXELS\tSet to 1 to convert between CCIR 601 and JPEG automatically (default=dont care)\n\tVEEJAY_INTERPOLATE_CHROMA\tSet to 1 if you wish to interpolate every chroma sample when scaling (default=0)\n\tVEEJAY_CAPTURE_DRIVER\t\tSet to \"unicap\" or \"v4lutils\" (default=v4lutils)\n\tVEEJAY_SDL_KEY_REPEAT_INTERVAL\tinterval of key pressed to repeat while pressed down.\n\tVEEJAY_PLAYBACK_CACHE\t\tSample cache size in MB - by default, veejay takes 30 percent of total RAM\n\tVEEJAY_SDL_KEY_REPEAT_DELAY\tDelay key repeat in ms\n\tVEEJAY_FULLSCREEN\t\tStart in fullscreen (1) or windowed (0) mode\n\tVEEJAY_SCREEN_GEOMETRY\t\tSpecifiy a geometry for veejay to position the video window.\n\tVEEJAY_SCREEN_SIZE\t\tSize of video window, defaults to full screen size.\n\tVEEJAY_RUN_MODE\t\t\tRun in \"classic\" (352x288 Dummy) or default (720x576). \n");
			fprintf(stdout, "\n\n\tExample for bash:\n\t\t\t$ export VEEJAY_AUTO_SCALE_PIXEL=1\n");


		veejay_free(info);
		return 0;
	}

	if( vj_el_get_mem_size() == 0 )
		prepare_cache_line( max_mem_, n_slots_ );

	veejay_check_homedir( info );

	sigsegfault_handler();

    	sigemptyset(&(settings->signal_set));
	sigaddset(&(settings->signal_set), SIGINT);
	sigaddset(&(settings->signal_set), SIGPIPE);
	sigaddset(&(settings->signal_set), SIGILL);
//	sigaddset(&(settings->signal_set), SIGSEGV);
	sigaddset(&(settings->signal_set), SIGFPE );
	sigaddset(&(settings->signal_set), SIGTERM );
	sigaddset(&(settings->signal_set), SIGABRT);
	sigaddset(&(settings->signal_set), SIGPWR );
	sigaddset(&(settings->signal_set), SIGQUIT );

	sigfillset( &allsignals );
	action.sa_handler = donothing;
	action.sa_mask = allsignals;
	action.sa_flags = SA_SIGINFO | SA_ONESHOT ; //SA_RESTART | SA_RESETHAND;

	signal( SIGPIPE, SIG_IGN );

	for( i = 1; i < NSIG; i ++ )
		if( sigismember( &(settings->signal_set), i ))
			sigaction( i, &action, 0 );
	
	char *mem_func = get_memcpy_descr();
	if(mem_func)
	{
		veejay_msg(VEEJAY_MSG_INFO, "Using SIMD %s", mem_func);
		free(mem_func);
	}
	info->use_keyb = use_keyb;
	info->use_mouse = use_mouse;
	info->show_cursor = show_cursor;


	if(veejay_init(
		info,
		default_geometry_x,
		default_geometry_y,
		NULL,
		live,
	    ta	)< 0)
	{	
		veejay_msg(VEEJAY_MSG_ERROR, "Cannot start veejay");
		return 0;
	}

	if(auto_loop)
		veejay_auto_loop(info);


	print_license();

	veejay_init_msg_ring();  // rest of logging to screen

    	if(!veejay_main(info))
	{
	    veejay_msg(VEEJAY_MSG_ERROR, "Cannot start main playback cycle");
		veejay_free(info);
		return 1;
	}

	
	veejay_msg(VEEJAY_MSG_DEBUG, "Started playback");

	int current_state = LAVPLAY_STATE_PLAYING;

	req.tv_sec = 0;
	req.tv_nsec = 4000 * 1000; 

	while( 1 ) { //@ until your PC stops working
		
		clock_nanosleep( CLOCK_REALTIME, 0, &req, NULL );

		current_state = veejay_get_state(info);
		
		if( current_state == LAVPLAY_STATE_STOP )
			break;
	}

	veejay_busy(info);			
	veejay_free(info);
	veejay_destroy_msg_ring();

	veejay_msg(VEEJAY_MSG_INFO, "Thank you for using Veejay");

	return 0;
}
static int dpram_thread(void *data)
{
	int ret = 0;
	//unsigned long flags;
	struct file *filp;

	dpram_task = current;

	daemonize("dpram_thread");
	//reparent_to_init();  // for 2.6 kernel porting : this seems not to be used in driver
	// current->tty = NULL; // for 2.6 kernel porting
	
	strcpy(current->comm, "multipdp");

	/* set signals to accept */
	//spin_lock_irqsave(&current->sigmask_lock, flags); // for 2.6 kernel proting
	siginitsetinv(&current->blocked, sigmask(SIGUSR1));
	//recalc_sigpending(current);
	recalc_sigpending();
	//spin_unlock_irqrestore(&current->sigmask_lock, flags); // for 2.6 kernel proting

	filp = dpram_open();
	if (filp == NULL) {
		goto out;
	}
	dpram_filp = filp;

	/* send start signal */
	complete(&dpram_complete);

	while (1) {
		ret = dpram_poll(filp);

		if (ret == -ERESTARTSYS) {
			if (sigismember(&current->pending.signal, SIGUSR1)) {
				printk(KERN_ERR "MULTIPDP (%s) DPRAM device communication interrupted\n",__func__);
				sigdelset(&current->pending.signal, SIGUSR1);
				recalc_sigpending();
				ret = 0;
				break;
			}
		}
		
		else if (ret < 0) {
			EPRINTK("dpram_poll() failed\n");
			break;
		}
		
		else {
			char ch;
			dpram_read(dpram_filp, &ch, sizeof(ch));

			if (ch == 0x7f) {
				pdp_demux();
			}
		}

		try_to_freeze();
	}

	dpram_close(filp);
	dpram_filp = NULL;

out:
	dpram_task = NULL;

	/* send finish signal and exit */
	complete_and_exit(&dpram_complete, ret);
}
Beispiel #10
0
/*
 * This is not really a trans2 request, we assume that you only have
 * one packet to send.
 */
int
smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command,
		   int ldata, unsigned char *data,
		   int lparam, unsigned char *param,
		   int *lrdata, unsigned char **rdata,
		   int *lrparam, unsigned char **rparam)
{
	sigset_t old_set;
	unsigned long flags, sigpipe;
	mm_segment_t fs;
	int result;

	pr_debug("smb_trans2_request: com=%d, ld=%d, lp=%d\n",
		 trans2_command, ldata, lparam);

	/*
	 * These are initialized in smb_request_ok, but not here??
	 */
	server->rcls = 0;
	server->err = 0;

	result = -EIO;
	if (server->state != CONN_VALID)
		goto out;

	if ((result = smb_dont_catch_keepalive(server)) != 0)
		goto bad_conn;

	spin_lock_irqsave(&current->sigmask_lock, flags);
	sigpipe = sigismember(&current->signal, SIGPIPE);
	old_set = current->blocked;
	siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
	recalc_sigpending(current);
	spin_unlock_irqrestore(&current->sigmask_lock, flags);

	fs = get_fs();
	set_fs(get_ds());

	result = smb_send_trans2(server, trans2_command,
				 ldata, data, lparam, param);
	if (result >= 0)
	{
		result = smb_receive_trans2(server,
					    lrdata, rdata, lrparam, rparam);
	}

	/* read/write errors are handled by errno */
	spin_lock_irqsave(&current->sigmask_lock, flags);
	if (result == -EPIPE && !sigpipe)
		sigdelset(&current->signal, SIGPIPE);
	current->blocked = old_set;
	recalc_sigpending(current);
	spin_unlock_irqrestore(&current->sigmask_lock, flags);

	set_fs(fs);

	if (result >= 0)
	{
		int result2 = smb_catch_keepalive(server);
		if (result2 < 0)
		{
			result = result2;
		}
	}
	if (result < 0)
		goto bad_conn;
	/*
	 * Check for fatal server errors ...
	 */
	if (server->rcls) {
		int error = smb_errno(server);
		if (error == EBADSLT) {
			printk("smb_request: tree ID invalid\n");
			result = error;
			goto bad_conn;
		}
	}

out:
	return result;

bad_conn:
#ifdef SMBFS_PARANOIA
printk("smb_trans2_request: result=%d, setting invalid\n", result);
#endif
	server->state = CONN_INVALID;
	smb_invalidate_inodes(server);
	goto out;
}
/*
 *  stress_sigpending
 *	stress sigpending system call
 */
int stress_sigpending(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	struct sigaction new_action;
	sigset_t sigset;
	const pid_t mypid = getpid();

	(void)instance;

	memset(&new_action, 0, sizeof new_action);
	new_action.sa_handler = stress_usr1_handler;
	sigemptyset(&new_action.sa_mask);
	new_action.sa_flags = 0;

	if (sigaction(SIGUSR1, &new_action, NULL) < 0) {
		pr_failed_err(name, "sigaction");
		return EXIT_FAILURE;
	}


	do {
		sigemptyset(&sigset);
		sigaddset(&sigset, SIGUSR1);
		if (sigprocmask(SIG_SETMASK, &sigset, NULL) < 0) {
			pr_failed_err(name, "sigprocmask");
			return EXIT_FAILURE;
		}

		(void)kill(mypid, SIGUSR1);
		if (sigpending(&sigset) < 0) {
			pr_failed_err(name, "sigpending");
			continue;
		}
		/* We should get a SIGUSR1 here */
		if (!sigismember(&sigset, SIGUSR1)) {
			pr_failed_err(name, "sigismember");
			continue;
		}

		/* Unmask signal, signal is handled */
		sigemptyset(&sigset);
		sigprocmask(SIG_SETMASK, &sigset, NULL);

		/* And it is no longer pending */
		if (sigpending(&sigset) < 0) {
			pr_failed_err(name, "sigpending");
			continue;
		}
		if (sigismember(&sigset, SIGUSR1)) {
			pr_failed_err(name, "sigismember");
			continue;
		}
		/* Success! */
		(*counter)++;
	} while (opt_do_run && (!max_ops || *counter < max_ops));

	return EXIT_SUCCESS;
}
Beispiel #12
0
/*
 * Called with the server locked
 */
int
smb_request(struct smb_sb_info *server)
{
	unsigned long flags, sigpipe;
	mm_segment_t fs;
	sigset_t old_set;
	int len, result;
	unsigned char *buffer;

	result = -EBADF;
	buffer = server->packet;
	if (!buffer)
		goto bad_no_packet;

	result = -EIO;
	if (server->state != CONN_VALID)
		goto bad_no_conn;

	if ((result = smb_dont_catch_keepalive(server)) != 0)
		goto bad_conn;

	len = smb_len(buffer) + 4;
	pr_debug("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);

	spin_lock_irqsave(&current->sigmask_lock, flags);
	sigpipe = sigismember(&current->signal, SIGPIPE);
	old_set = current->blocked;
	siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
	recalc_sigpending(current);
	spin_unlock_irqrestore(&current->sigmask_lock, flags);

	fs = get_fs();
	set_fs(get_ds());

	result = smb_send_raw(server_sock(server), (void *) buffer, len);
	if (result > 0)
	{
		result = smb_receive(server);
	}

	/* read/write errors are handled by errno */
	spin_lock_irqsave(&current->sigmask_lock, flags);
	if (result == -EPIPE && !sigpipe)
		sigdelset(&current->signal, SIGPIPE);
	current->blocked = old_set;
	recalc_sigpending(current);
	spin_unlock_irqrestore(&current->sigmask_lock, flags);

	set_fs(fs);

	if (result >= 0)
	{
		int result2 = smb_catch_keepalive(server);
		if (result2 < 0)
		{
			printk("smb_request: catch keepalive failed\n");
			result = result2;
		}
	}
	if (result < 0)
		goto bad_conn;
	/*
	 * Check for fatal server errors ...
	 */
	if (server->rcls) {
		int error = smb_errno(server);
		if (error == EBADSLT) {
			printk("smb_request: tree ID invalid\n");
			result = error;
			goto bad_conn;
		}
	}

out:
	pr_debug("smb_request: result = %d\n", result);
	return result;
	
bad_conn:
#ifdef SMBFS_PARANOIA
printk("smb_request: result %d, setting invalid\n", result);
#endif
	server->state = CONN_INVALID;
	smb_invalidate_inodes(server);
	goto out;		
bad_no_packet:
	printk("smb_request: no packet!\n");
	goto out;
bad_no_conn:
	printk("smb_request: connection %d not valid!\n", server->state);
	goto out;
}
Beispiel #13
0
/*===========================================================================*
 *				do_exec					     *
 *===========================================================================*/
PUBLIC int do_exec()
{
/* Perform the execve(name, argv, envp) call.  The user library builds a
 * complete stack image, including pointers, args, environ, etc.  The stack
 * is copied to a buffer inside MM, and then to the new core image.
 */

  register struct mproc *rmp;
  struct mproc *sh_mp;
  int m, r, fd, ft, sn;
  static char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
  static char name_buf[PATH_MAX]; /* the name of the file to exec */
  char *new_sp, *basename;
  vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
  phys_bytes tot_bytes;		/* total space for program, including gap */
  long sym_bytes;
  vir_clicks sc;
  struct stat s_buf;
  vir_bytes pc;

  /* Do some validity checks. */
  rmp = mp;
  stk_bytes = (vir_bytes) stack_bytes;
  if (stk_bytes > ARG_MAX) return(ENOMEM);	/* stack too big */
  if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL);

  /* Get the exec file name and see if the file is executable. */
  src = (vir_bytes) exec_name;
  dst = (vir_bytes) name_buf;
  r = sys_copy(who, D, (phys_bytes) src,
		MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len);
  if (r != OK) return(r);	/* file name not in user data segment */
  tell_fs(CHDIR, who, FALSE, 0);	/* switch to the user's FS environ. */
  fd = allowed(name_buf, &s_buf, X_BIT);	/* is file executable? */
  if (fd < 0) return(fd);	/* file was not executable */

  /* Read the file header and extract the segment sizes. */
  sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, 
					&tot_bytes, &sym_bytes, sc, &pc);
  if (m < 0) {
	close(fd);		/* something wrong with header */
	return(ENOEXEC);
  }

  /* Fetch the stack from the user before destroying the old core image. */
  src = (vir_bytes) stack_ptr;
  dst = (vir_bytes) mbuf;
  r = sys_copy(who, D, (phys_bytes) src,
  			MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes);
  if (r != OK) {
	close(fd);		/* can't fetch stack (e.g. bad virtual addr) */
	return(EACCES);
  }

  /* Can the process' text be shared with that of one already running? */
  sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime);

  /* Allocate new memory and release old memory.  Fix map and tell kernel. */
  r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes);
  if (r != OK) {
	close(fd);		/* insufficient core or program too big */
	return(r);
  }

  /* Save file identification to allow it to be shared. */
  rmp->mp_ino = s_buf.st_ino;
  rmp->mp_dev = s_buf.st_dev;
  rmp->mp_ctime = s_buf.st_ctime;

  /* Patch up stack and copy it from MM to new core image. */
  vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
  vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
  vsp -= stk_bytes;
  patch_ptr(mbuf, vsp);
  src = (vir_bytes) mbuf;
  r = sys_copy(MM_PROC_NR, D, (phys_bytes) src,
  			who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes);
  if (r != OK) panic("do_exec stack copy err", NO_NUM);

  /* Read in text and data segments. */
  if (sh_mp != NULL) {
	lseek(fd, (off_t) text_bytes, SEEK_CUR);  /* shared: skip text */
  } else {
	load_seg(fd, T, text_bytes);
  }
  load_seg(fd, D, data_bytes);

#if (SHADOWING == 1)
  if (lseek(fd, (off_t)sym_bytes, SEEK_CUR) == (off_t) -1) ;	/* error */
  if (relocate(fd, (unsigned char *)mbuf) < 0) 	;		/* error */
  pc += (vir_bytes) rp->mp_seg[T].mem_vir << CLICK_SHIFT;
#endif

  close(fd);			/* don't need exec file any more */

  /* Take care of setuid/setgid bits. */
  if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
	if (s_buf.st_mode & I_SET_UID_BIT) {
		rmp->mp_effuid = s_buf.st_uid;
		tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
	}
	if (s_buf.st_mode & I_SET_GID_BIT) {
		rmp->mp_effgid = s_buf.st_gid;
		tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
	}
  }

  /* Save offset to initial argc (for ps) */
  rmp->mp_procargs = vsp;

  /* Fix 'mproc' fields, tell kernel that exec is done,  reset caught sigs. */
  for (sn = 1; sn <= _NSIG; sn++) {
	if (sigismember(&rmp->mp_catch, sn)) {
		sigdelset(&rmp->mp_catch, sn);
		rmp->mp_sigact[sn].sa_handler = SIG_DFL;
		sigemptyset(&rmp->mp_sigact[sn].sa_mask);
	}
  }

  rmp->mp_flags &= ~SEPARATE;	/* turn off SEPARATE bit */
  rmp->mp_flags |= ft;		/* turn it on for separate I & D files */
  new_sp = (char *) vsp;

  tell_fs(EXEC, who, 0, 0);	/* allow FS to handle FD_CLOEXEC files */

  /* System will save command line for debugging, ps(1) output, etc. */
  basename = strrchr(name_buf, '/');
  if (basename == NULL) basename = name_buf; else basename++;
  sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc);
  return(OK);
}
Beispiel #14
0
/* Handlers intialization */
void
signal_handler_init(int remember)
{
	sigset_t sset;
	int sig;
	struct sigaction act, oact;
	int n;

#ifdef HAVE_PIPE2
	n = pipe2(signal_pipe, O_CLOEXEC | O_NONBLOCK);
#else
	n = pipe(signal_pipe);
#endif

	assert(!n);
	if (n)
		log_message(LOG_INFO, "BUG - pipe in signal_handler_init failed (%s), please report", strerror(errno));

#ifndef HAVE_PIPE2
	fcntl(signal_pipe[0], F_SETFL, O_NONBLOCK | fcntl(signal_pipe[0], F_GETFL));
	fcntl(signal_pipe[1], F_SETFL, O_NONBLOCK | fcntl(signal_pipe[1], F_GETFL));

	fcntl(signal_pipe[0], F_SETFD, FD_CLOEXEC | fcntl(signal_pipe[0], F_GETFD));
	fcntl(signal_pipe[1], F_SETFD, FD_CLOEXEC | fcntl(signal_pipe[1], F_GETFD));
#endif

	signal_SIGHUP_handler = NULL;
	signal_SIGINT_handler = NULL;
	signal_SIGTERM_handler = NULL;
	signal_SIGCHLD_handler = NULL;
	signal_SIGUSR1_handler = NULL;
	signal_SIGUSR2_handler = NULL;

	/* Ignore all signals set to default (except essential ones) */
	sigfillset(&sset);
	sigdelset(&sset, SIGILL);
	sigdelset(&sset, SIGFPE);
	sigdelset(&sset, SIGSEGV);
	sigdelset(&sset, SIGBUS);
	sigdelset(&sset, SIGKILL);
	sigdelset(&sset, SIGSTOP);

	act.sa_handler = SIG_IGN;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;

	if (remember) {
		sigemptyset(&ign_sig);
		sigemptyset(&dfl_sig);
	}

	for (sig = 1; sig <= SIGRTMAX; sig++) {
		if (sigismember(&sset, sig)){
			sigaction(sig, NULL, &oact);

			/* Remember the original disposition, and ignore
			 * any default action signals
			 */
			if (oact.sa_handler == SIG_IGN) {
				if (remember)
					sigaddset(&ign_sig, sig);
			}
			else {
				sigaction(sig, &act, NULL);
				if (remember)
					sigaddset(&dfl_sig, sig);
			}
		}
	}
}
Beispiel #15
0
int
main(int argc, char *argv[])
{
	unsigned char msg[MSG_SIZE_RECV];
	char pidstr[16];
	ssize_t ret;
	int c, log_method;
	char *logfile, *pidfile;
	sigset_t oset, nset;
	int facility, fd;
	char *username = NULL;
	char *chrootdir = NULL;
	int singleprocess = 0;
#ifdef HAVE_GETOPT_LONG
	int opt_idx;
#endif

	pname = ((pname=strrchr(argv[0],'/')) != NULL)?pname+1:argv[0];

	srand((unsigned int)time(NULL));

	log_method = L_STDERR_SYSLOG;
	logfile = PATH_RADVD_LOG;
	conf_file = PATH_RADVD_CONF;
	facility = LOG_FACILITY;
	pidfile = PATH_RADVD_PID;

	/* parse args */
#ifdef HAVE_GETOPT_LONG
	while ((c = getopt_long(argc, argv, "d:C:l:m:p:t:u:vhs", prog_opt, &opt_idx)) > 0)
#else
	while ((c = getopt(argc, argv, "d:C:l:m:p:t:u:vhs")) > 0)
#endif
	{
		switch (c) {
		case 'C':
			conf_file = optarg;
			break;
		case 'd':
			set_debuglevel(atoi(optarg));
			break;
		case 'f':
			facility = atoi(optarg);
			break;
		case 'l':
			logfile = optarg;
			break;
		case 'p':
			pidfile = optarg;
			break;
		case 'm':
			if (!strcmp(optarg, "syslog"))
			{
				log_method = L_SYSLOG;
			}
			else if (!strcmp(optarg, "stderr_syslog"))
			{
				log_method = L_STDERR_SYSLOG;
			}
			else if (!strcmp(optarg, "stderr"))
			{
				log_method = L_STDERR;
			}
			else if (!strcmp(optarg, "logfile"))
			{
				log_method = L_LOGFILE;
			}
			else if (!strcmp(optarg, "none"))
			{
				log_method = L_NONE;
			}
			else
			{
				fprintf(stderr, "%s: unknown log method: %s\n", pname, optarg);
				exit(1);
			}
			break;
		case 't':
			chrootdir = strdup(optarg);
			break;
		case 'u':
			username = strdup(optarg);
			break;
		case 'v':
			version();
			break;
		case 's':
			singleprocess = 1;
			break;
		case 'h':
			usage();
#ifdef HAVE_GETOPT_LONG
		case ':':
			fprintf(stderr, "%s: option %s: parameter expected\n", pname,
				prog_opt[opt_idx].name);
			exit(1);
#endif
		case '?':
			exit(1);
		}
	}

	if (chrootdir) {
		if (!username) {
			fprintf(stderr, "Chroot as root is not safe, exiting\n");
			exit(1);
		}
		
		if (chroot(chrootdir) == -1) {
			perror("chroot");
			exit (1);
		}
		
		if (chdir("/") == -1) {
			perror("chdir");
			exit (1);
		}
		/* username will be switched later */
	}
	
	if (log_open(log_method, pname, logfile, facility) < 0)
		exit(1);

	flog(LOG_INFO, "version %s started", VERSION);

	/* get a raw socket for sending and receiving ICMPv6 messages */
	sock = open_icmpv6_socket();
	if (sock < 0)
		exit(1);

	/* check that 'other' cannot write the file
         * for non-root, also that self/own group can't either
         */
	if (check_conffile_perm(username, conf_file) < 0) {
		if (get_debuglevel() == 0)
			exit(1);
		else
			flog(LOG_WARNING, "Insecure file permissions, but continuing anyway");
	}
	
	/* if we know how to do it, check whether forwarding is enabled */
	if (check_ip6_forwarding()) {
		if (get_debuglevel() == 0) {
			flog(LOG_ERR, "IPv6 forwarding seems to be disabled, exiting");
			exit(1);
		}
		else
			flog(LOG_WARNING, "IPv6 forwarding seems to be disabled, but continuing anyway.");
	}

	/* parse config file */
	if (readin_config(conf_file) < 0)
		exit(1);

	/* drop root privileges if requested. */
	if (username) {
		if (!singleprocess) {
		 	dlog(LOG_DEBUG, 3, "Initializing privsep");
		 	if (privsep_init() < 0)
				flog(LOG_WARNING, "Failed to initialize privsep.");
		}

		if (drop_root_privileges(username) < 0)
			exit(1);
	}

	if ((fd = open(pidfile, O_RDONLY, 0)) > 0)
	{
		ret = read(fd, pidstr, sizeof(pidstr) - 1);
		if (ret < 0)
		{
			flog(LOG_ERR, "cannot read radvd pid file, terminating: %s", strerror(errno));
			exit(1);
		}
		pidstr[ret] = '\0';
		if (!kill((pid_t)atol(pidstr), 0))
		{
			flog(LOG_ERR, "radvd already running, terminating.");
			exit(1);
		}
		close(fd);
		fd = open(pidfile, O_CREAT|O_TRUNC|O_WRONLY, 0644);
	}
	else	/* FIXME: not atomic if pidfile is on an NFS mounted volume */
		fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644);

	if (fd < 0)
	{
		flog(LOG_ERR, "cannot create radvd pid file, terminating: %s", strerror(errno));
		exit(1);
	}
	
	/*
	 * okay, config file is read in, socket and stuff is setup, so
	 * lets fork now...
	 */

	if (get_debuglevel() == 0) {

		/* Detach from controlling terminal */
		if (daemon(0, 0) < 0)
			perror("daemon");

		/* close old logfiles, including stderr */
		log_close();
		
		/* reopen logfiles, but don't log to stderr unless explicitly requested */
		if (log_method == L_STDERR_SYSLOG)
			log_method = L_SYSLOG;
		if (log_open(log_method, pname, logfile, facility) < 0)
			exit(1);

	}

	/*
	 *	config signal handlers, also make sure ALRM isn't blocked and raise a warning if so
	 *      (some stupid scripts/pppd appears to do this...)
	 */
	sigemptyset(&nset);
	sigaddset(&nset, SIGALRM);
	sigprocmask(SIG_UNBLOCK, &nset, &oset);
	if (sigismember(&oset, SIGALRM))
		flog(LOG_WARNING, "SIGALRM has been unblocked. Your startup environment might be wrong.");

	signal(SIGHUP, sighup_handler);
	signal(SIGTERM, sigterm_handler);
	signal(SIGINT, sigint_handler);

	snprintf(pidstr, sizeof(pidstr), "%ld\n", (long)getpid());
	
	write(fd, pidstr, strlen(pidstr));
	
	close(fd);

	config_interface();
	kickoff_adverts();

	/* enter loop */

	for (;;)
	{
		int len, hoplimit;
		struct sockaddr_in6 rcv_addr;
		struct in6_pktinfo *pkt_info = NULL;
		
		len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit);
		if (len > 0)
			process(sock, IfaceList, msg, len, 
				&rcv_addr, pkt_info, hoplimit);

		if (sigterm_received || sigint_received) {
			stop_adverts();
			break;
		}

		if (sighup_received)
		{
			reload_config();		
			sighup_received = 0;
		}
	}
	
	unlink(pidfile);
	exit(0);
}
Beispiel #16
0
 int main()
 {
         sigset_t set,pendset;
         struct sigaction action1,action2;
 
         //initialize the set empty
         if(sigemptyset(&set)<0)
         {
                 perror("sigemptyset\n");
                 exit(1);
         }
 
         if(sigaddset(&set,SIGQUIT)<0)
         {
                 perror("sigaddset\n");
                 exit(1);
         }
         if(sigaddset(&set,SIGINT)<0)
         {
                 perror("sigaddset\n");
                 exit(1);
         }
 
         if(sigismember(&set,SIGINT))
         {
                 sigemptyset(&action1.sa_mask);
                 action1.sa_handler=my_func;
                 action1.sa_flags=0;
                 sigaction(SIGINT,&action1,NULL);
 
         }
         if(sigismember(&set,SIGQUIT))
         {       
                 sigemptyset(&action2.sa_mask);
                 action2.sa_handler=SIG_DFL;
                 action2.sa_flags=0;
                 sigaction(SIGQUIT,&action2,NULL);
 
         }
  
         if(sigprocmask(SIG_BLOCK,&set,NULL)<0)
         {
                 perror("sigprocmask");
                 exit(1);
         }
         else
         {       
                 printf("Signal set was blocked,Press any key!\n");
                 getchar();
         }
 
         if(sigprocmask(SIG_UNBLOCK,&set,NULL)<0)
         {
                 perror("sigprocmask");
                 exit(1);
         }
         else
         {
                 printf("Signal set is in unblock state.\n");
         }
         
         while(1);
         
         exit(0);
 
 
 }
/*
 * This is the NFS server kernel thread
 */
static void
nfsd(struct svc_rqst *rqstp)
{
	struct svc_serv	*serv = rqstp->rq_server;
	struct fs_struct *fsp;
	int		err;
	struct nfsd_list me;
	sigset_t shutdown_mask, allowed_mask;

	/* Lock module and set up kernel thread */
	lock_kernel();
	daemonize("nfsd");
	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;

	/* After daemonize() this kernel thread shares current->fs
	 * with the init process. We need to create files with a
	 * umask of 0 instead of init's umask. */
	fsp = copy_fs_struct(current->fs);
	if (!fsp) {
		printk("Unable to start nfsd thread: out of memory\n");
		goto out;
	}
	exit_fs(current);
	current->fs = fsp;
	current->fs->umask = 0;

	siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS);
	siginitsetinv(&allowed_mask, ALLOWED_SIGS);

	nfsdstats.th_cnt++;

	lockd_up();				/* start lockd */

	me.task = current;
	list_add(&me.list, &nfsd_list);

	unlock_kernel();

	/*
	 * We want less throttling in balance_dirty_pages() so that nfs to
	 * localhost doesn't cause nfsd to lock up due to all the client's
	 * dirty pages.
	 */
	current->flags |= PF_LESS_THROTTLE;

	/*
	 * The main request loop
	 */
	for (;;) {
		/* Block all but the shutdown signals */
		sigprocmask(SIG_SETMASK, &shutdown_mask, NULL);

		/*
		 * Find a socket with data available and call its
		 * recvfrom routine.
		 */
		while ((err = svc_recv(serv, rqstp,
				       60*60*HZ)) == -EAGAIN)
			;
		if (err < 0)
			break;
		update_thread_usage(atomic_read(&nfsd_busy));
		atomic_inc(&nfsd_busy);

		/* Lock the export hash tables for reading. */
		exp_readlock();

		/* Process request with signals blocked.  */
		sigprocmask(SIG_SETMASK, &allowed_mask, NULL);

		svc_process(serv, rqstp);

		/* Unlock export hash tables */
		exp_readunlock();
		update_thread_usage(atomic_read(&nfsd_busy));
		atomic_dec(&nfsd_busy);
	}

	if (err != -EINTR) {
		printk(KERN_WARNING "nfsd: terminating on error %d\n", -err);
	} else {
		unsigned int	signo;

		for (signo = 1; signo <= _NSIG; signo++)
			if (sigismember(&current->pending.signal, signo) &&
			    !sigismember(&current->blocked, signo))
				break;
		err = signo;
	}

	lock_kernel();

	/* Release lockd */
	lockd_down();

	/* Check if this is last thread */
	if (serv->sv_nrthreads==1) {
		
		printk(KERN_WARNING "nfsd: last server has exited\n");
		if (err != SIG_NOCLEAN) {
			printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
			nfsd_export_flush();
		}
		nfsd_serv = NULL;
	        nfsd_racache_shutdown();	/* release read-ahead cache */
		nfs4_state_shutdown();
	}
	list_del(&me.list);
	nfsdstats.th_cnt --;

out:
	/* Release the thread */
	svc_exit_thread(rqstp);

	/* Release module */
	module_put_and_exit(0);
}
Beispiel #18
0
static int exec_conf(void)
{
	int pipefd[2], stat, size;
	struct sigaction sa;
	sigset_t sset, osset;

	sigemptyset(&sset);
	sigaddset(&sset, SIGINT);
	sigprocmask(SIG_BLOCK, &sset, &osset);

	signal(SIGINT, SIG_DFL);

	sa.sa_handler = winch_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	sigaction(SIGWINCH, &sa, NULL);

	*argptr++ = NULL;

	pipe(pipefd);
	pid = fork();
	if (pid == 0) {
		sigprocmask(SIG_SETMASK, &osset, NULL);
		dup2(pipefd[1], 2);
		close(pipefd[0]);
		close(pipefd[1]);
		execv(args[0], args);
		_exit(EXIT_FAILURE);
	}

	close(pipefd[1]);
	bufptr = input_buf;
	while (1) {
		size = input_buf + sizeof(input_buf) - bufptr;
		size = read(pipefd[0], bufptr, size);
		if (size <= 0) {
			if (size < 0) {
				if (errno == EINTR || errno == EAGAIN)
					continue;
				perror("read");
			}
			break;
		}
		bufptr += size;
	}
	*bufptr++ = 0;
	close(pipefd[0]);
	waitpid(pid, &stat, 0);

	if (do_resize) {
		init_wsize();
		do_resize = 0;
		sigprocmask(SIG_SETMASK, &osset, NULL);
		return -1;
	}
	if (WIFSIGNALED(stat)) {
		printf("\finterrupted(%d)\n", WTERMSIG(stat));
		exit(1);
	}
#if 0
	printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf);
	sleep(1);
#endif
	sigpending(&sset);
	if (sigismember(&sset, SIGINT)) {
		printf("\finterrupted\n");
		exit(1);
	}
	sigprocmask(SIG_SETMASK, &osset, NULL);

	return WEXITSTATUS(stat);
}
Beispiel #19
0
/* Terminate handler */
static void
sigend(void *v, int sig)
{
	int status;
	int ret;
	int wait_count = 0;
	sigset_t old_set, child_wait;
	struct timespec timeout = {
		.tv_sec = CHILD_WAIT_SECS,
		.tv_nsec = 0
	};
	struct timeval start_time, now;

	/* register the terminate thread */
	thread_add_terminate_event(master);

	log_message(LOG_INFO, "Stopping");
	sigprocmask(0, NULL, &old_set);
	if (!sigismember(&old_set, SIGCHLD)) {
		sigemptyset(&child_wait);
		sigaddset(&child_wait, SIGCHLD);
		sigprocmask(SIG_BLOCK, &child_wait, NULL);
	}

	if (vrrp_child > 0) {
		kill(vrrp_child, SIGTERM);
		wait_count++;
	}
	if (checkers_child > 0) {
		kill(checkers_child, SIGTERM);
		wait_count++;
	}

	gettimeofday(&start_time, NULL);
	while (wait_count) {
		ret = sigtimedwait(&child_wait, NULL, &timeout);
		if (ret == -1) {
			if (errno == EINTR)
				continue;
			if (errno == EAGAIN)
				break;
		}

		if (vrrp_child > 0 && vrrp_child == waitpid(vrrp_child, &status, WNOHANG)) {
			report_child_status(status, vrrp_child, PROG_VRRP);
			wait_count--;
		}

		if (checkers_child > 0 && checkers_child == waitpid(checkers_child, &status, WNOHANG)) {
			report_child_status(status, checkers_child, PROG_CHECK);
			wait_count--;
		}
		if (wait_count) {
			gettimeofday(&now, NULL);
			if (now.tv_usec < start_time.tv_usec) {
				timeout.tv_nsec = (start_time.tv_usec - now.tv_usec) * 1000;
				timeout.tv_sec = CHILD_WAIT_SECS - (now.tv_sec - start_time.tv_sec);
			} else if (now.tv_usec == start_time.tv_usec) {
				timeout.tv_nsec = 0;
				timeout.tv_sec = CHILD_WAIT_SECS - (now.tv_sec - start_time.tv_sec);
			} else {
				timeout.tv_nsec = (1000000L + start_time.tv_usec - now.tv_usec) * 1000;
				timeout.tv_sec = CHILD_WAIT_SECS - (now.tv_sec - start_time.tv_sec + 1);
			}

			timeout.tv_nsec = (start_time.tv_usec - now.tv_usec) * 1000;
			timeout.tv_sec = CHILD_WAIT_SECS - (now.tv_sec - start_time.tv_sec);
			if (timeout.tv_nsec < 0) {
				timeout.tv_nsec += 1000000000L;
				timeout.tv_sec--;
			}
		}
	}

	if (!sigismember(&old_set, SIGCHLD))
		sigprocmask(SIG_UNBLOCK, &child_wait, NULL);
}

/* Initialize signal handler */
static void
signal_init(void)
{
	signal_handler_init();
	signal_set(SIGHUP, propogate_signal, NULL);
	signal_set(SIGUSR1, propogate_signal, NULL);
	signal_set(SIGUSR2, propogate_signal, NULL);
	signal_set(SIGINT, sigend, NULL);
	signal_set(SIGTERM, sigend, NULL);
	signal_ignore(SIGPIPE);
}
Beispiel #20
0
int rpmsqIsCaught(int signum)
{
    return sigismember(&rpmsqCaught, signum);
}
Beispiel #21
0
int sig_received(FAR _TCB *stcb, siginfo_t *info)
{
  irqstate_t saved_state;
  int        ret = ERROR;

  sdbg("TCB=0x%08x signo=%d code=%d value=%d mask=%08x\n",
       stcb, info->si_signo, info->si_code,
       info->si_value.sival_int, stcb->sigprocmask);

  if (stcb && info)
    {
      ret = OK;

      /****************** MASKED SIGNAL HANDLING ******************/

      /* Check if the signal is masked -- if it is, it will be added to the
       * list of pending signals.
       */

      if (sigismember(&stcb->sigprocmask, info->si_signo))
        {
          /* Check if the task is waiting for this pending signal.  If so,
           * then unblock it. This must be performed in a critical section
           * because signals can be queued from the interrupt level.
           */

          saved_state = irqsave();
          if (stcb->task_state == TSTATE_WAIT_SIG &&
              sigismember(&stcb->sigwaitmask, info->si_signo))
            {
              memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t));
              stcb->sigwaitmask = NULL_SIGNAL_SET;
              up_unblock_task(stcb);
              irqrestore(saved_state);
            }

          /* Its not one we are waiting for... Add it to the list of pending
           * signals.
           */

          else
            {
              irqrestore(saved_state);
              if (!sig_addpendingsignal(stcb, info))
                {
                  PANIC(OSERR_FAILEDTOADDSIGNAL);
                }
            }
        }

      /****************** UNMASKED SIGNAL HANDLING ******************/

      else
        {
          /* Queue any sigaction's requested by this task. */

          ret = sig_queueaction(stcb, info);

          /* Then schedule execution of the signal handling action on
           * the recipients thread.
           */

          up_schedule_sigaction(stcb, sig_deliver);

          /* Check if the task is waiting for an unmasked signal.  If so,
           * then unblock it. This must be performed in a critical section
           * because signals can be queued from the interrupt level.
           */

          saved_state = irqsave();
          if (stcb->task_state == TSTATE_WAIT_SIG)
            {
              memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t));
              stcb->sigwaitmask = NULL_SIGNAL_SET;
              up_unblock_task(stcb);
            }
          irqrestore(saved_state);

          /* If the task neither was waiting for the signal nor had a signal
           * handler attached to the signal, then the default action is
           * simply to ignore the signal
           */

          /****************** OTHER SIGNAL HANDLING ******************/

         /* If the task is blocked waiting for a semaphore, then that
          * task must be unblocked when a signal is received.
          */

         if (stcb->task_state == TSTATE_WAIT_SEM)
           {
             sem_waitirq(stcb);
           }

         /* If the task is blocked waiting on a message queue, then that
          * task must be unblocked when a signal is received.
          */

#ifndef CONFIG_DISABLE_MQUEUE
        if (stcb->task_state == TSTATE_WAIT_MQNOTEMPTY ||
            stcb->task_state == TSTATE_WAIT_MQNOTFULL)
           {
             mq_waitirq(stcb);
           }
#endif
       }
   }

  return ret;
}
Beispiel #22
0
static int group_signal_handler(pid_t pid, FAR void *arg)
{
  FAR struct group_signal_s *info = (FAR struct group_signal_s *)arg;
  FAR struct tcb_s *tcb;
  FAR sigactq_t *sigact;
  int ret;

  /* Get the TCB associated with the group member */

  tcb = sched_gettcb(pid);
  DEBUGASSERT(tcb != NULL && tcb->group != NULL && info != NULL);

  if (tcb)
    {
      /* Set this one as the default if we have not already set the default. */

      if (!info->dtcb)
        {
          info->dtcb = tcb;
        }

      /* Is the thread waiting for this signal (in this case, the signal is
       * probably blocked).
       */

      if (sigismember(&tcb->sigwaitmask, info->siginfo->si_signo) && !info->atcb)
        {
          /* Yes.. This means that the task is suspended, waiting for this
           * signal to occur. Stop looking and use this TCB.  The
           * requirement is this:  If a task group receives a signal and
           * more than one thread is waiting on that signal, then one and
           * only one indeterminate thread out of that waiting group will
           * receive the signal.
           */

          ret = sig_tcbdispatch(tcb, info->siginfo);
          if (ret < 0)
            {
              return ret;
            }

          /* Limit to one thread */

          info->atcb = tcb;
          if (info->ptcb != NULL)
            {
              return 1; /* Terminate the search */
            }
        }

      /* Is this signal unblocked on this thread? */

      if (!sigismember(&tcb->sigprocmask, info->siginfo->si_signo) &&
          !info->ptcb && tcb != info->atcb)
        {
          /* Yes.. remember this TCB if we have not encountered any
           * other threads that have the signal unblocked.
           */

          if (!info->utcb)
            {
              info->utcb = tcb;
            }

          /* Is there also a action associated with the task group? */

          sigact = sig_findaction(tcb->group, info->siginfo->si_signo);
          if (sigact)
            {
              /* Yes.. then use this thread.  The requirement is this:
               * If a task group receives a signal then one and only one
               * indeterminate thread in the task group which is not
               * blocking the signal will receive the signal.
               */

              ret = sig_tcbdispatch(tcb, info->siginfo);
              if (ret < 0)
                {
                  return ret;
                }

              /* Limit to one thread */

              info->ptcb = tcb;
              if (info->atcb != NULL)
                {
                  return 1; /* Terminate the search */
                }
            }
        }
    }

  return 0; /* Keep searching */
}
Beispiel #23
0
void
lock_mtab (void) {
	int tries = 3;
	char linktargetfile[MOUNTLOCK_LINKTARGET_LTH];

	at_die = unlock_mtab;

	if (!signals_have_been_setup) {
		int sig = 0;
		struct sigaction sa;

		sa.sa_handler = handler;
		sa.sa_flags = 0;
		sigfillset (&sa.sa_mask);
  
		while (sigismember (&sa.sa_mask, ++sig) != -1
		       && sig != SIGCHLD) {
			if (sig == SIGALRM)
				sa.sa_handler = setlkw_timeout;
			else
				sa.sa_handler = handler;
			sigaction (sig, &sa, (struct sigaction *) 0);
		}
		signals_have_been_setup = 1;
	}

	sprintf(linktargetfile, MOUNTLOCK_LINKTARGET, getpid ());

	/* Repeat until it was us who made the link */
	while (!we_created_lockfile) {
		struct flock flock;
		int errsv, fd, i, j;

		i = open (linktargetfile, O_WRONLY|O_CREAT, 0);
		if (i < 0) {
			int errsv = errno;
			/* linktargetfile does not exist (as a file)
			   and we cannot create it. Read-only filesystem?
			   Too many files open in the system?
			   Filesystem full? */
			die (EX_FILEIO, _("can't create lock file %s: %s "
			     "(use -n flag to override)"),
			     linktargetfile, strerror (errsv));
		}
		close(i);

		j = link(linktargetfile, MOUNTED_LOCK);
		errsv = errno;

		(void) unlink(linktargetfile);

		if (j == 0)
			we_created_lockfile = 1;

		if (j < 0 && errsv != EEXIST) {
			die (EX_FILEIO, _("can't link lock file %s: %s "
			     "(use -n flag to override)"),
			     MOUNTED_LOCK, strerror (errsv));
		}

		fd = open (MOUNTED_LOCK, O_WRONLY);

		if (fd < 0) {
			int errsv = errno;
			/* Strange... Maybe the file was just deleted? */
			if (errno == ENOENT && tries-- > 0)
				continue;
			die (EX_FILEIO, _("can't open lock file %s: %s "
			     "(use -n flag to override)"),
			     MOUNTED_LOCK, strerror (errsv));
		}

		flock.l_type = F_WRLCK;
		flock.l_whence = SEEK_SET;
		flock.l_start = 0;
		flock.l_len = 0;

		if (j == 0) {
			/* We made the link. Now claim the lock. */
			if (fcntl (fd, F_SETLK, &flock) == -1) {
				if (verbose) {
				    int errsv = errno;
				    printf(_("Can't lock lock file %s: %s\n"),
					   MOUNTED_LOCK, strerror (errsv));
				}
				/* proceed anyway */
			}
		} else {
			static int tries = 0;

			/* Someone else made the link. Wait. */
			alarm(LOCK_TIMEOUT);
			if (fcntl (fd, F_SETLKW, &flock) == -1) {
				int errsv = errno;
				die (EX_FILEIO, _("can't lock lock file %s: %s"),
				     MOUNTED_LOCK, (errno == EINTR) ?
				     _("timed out") : strerror (errsv));
			}
			alarm(0);
			/* Limit the number of iterations - maybe there
			   still is some old /etc/mtab~ */
			if (tries++ > 3) {
				if (tries > 5)
					die (EX_FILEIO, _("Cannot create link %s\n"
					    "Perhaps there is a stale lock file?\n"),
					     MOUNTED_LOCK);
				sleep(1);
			}
		}

		close(fd);
	}
}
Beispiel #24
0
/*
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 *
 * Note that we go through the signals twice: once to check the signals that
 * the kernel can handle, and then we build all the user-level signal handling
 * stack-frames in one go after that.
 */
int do_signal(struct pt_regs *regs, sigset_t *oldset)
{
	siginfo_t info;
	struct k_sigaction *ka;

	/*
	 * We want the common case to go fast, which
	 * is why we may in certain cases get here from
	 * kernel mode. Just return without doing anything
	 * if so.
	 */
	if (!user_mode(regs))
		return 1;

	if (!oldset)
		oldset = &current->blocked;

	for (;;) {
		unsigned long signr;

		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();

			/* We're back.  Did the debugger cancel the sig?  */
			if (!(signr = current->exit_code))
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr-1];
		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;
				/* FALLTHRU */

			case SIGSTOP:
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
				/* FALLTHRU */

			default:
				sig_exit(signr, exit_code, &info);
				/* NOTREACHED */
			}
		}

		/* Whee!  Actually deliver the signal.  */
		handle_signal(signr, ka, &info, oldset, regs);
		return 1;
	}

	/* Did we come from a system call? */
	if (regs->syscall_nr >= 0) {
		/* Restart the system call - no handlers present */
		if (regs->regs[0] == -ERESTARTNOHAND ||
		    regs->regs[0] == -ERESTARTSYS ||
		    regs->regs[0] == -ERESTARTNOINTR) {
			regs->regs[0] = regs->syscall_nr;
			regs->pc -= 2;
		}
	}
	return 0;
}
Beispiel #25
0
int is_ignored(int sig)
{
	return (sigismember(&current->blocked, sig) ||
	        current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);
}
Beispiel #26
0
/*
 * Note that `init' is a special process: it doesn't get signals it doesn't want to
 * handle.  Thus you cannot kill init even with a SIGKILL even by mistake.
 */
long
ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
{
	struct signal_struct *sig;
	struct k_sigaction *ka;
	siginfo_t info;
	long restart = in_syscall;
	long errno = scr->pt.r8;

	/*
	 * In the ia64_leave_kernel code path, we want the common case to go fast, which
	 * is why we may in certain cases get here from kernel mode. Just return without
	 * doing anything if so.
	 */
	if (!user_mode(&scr->pt))
		return 0;

	if (!oldset)
		oldset = &current->blocked;

#ifdef CONFIG_IA32_SUPPORT
	if (IS_IA32_PROCESS(&scr->pt)) {
		if (in_syscall) {
			if (errno >= 0)
				restart = 0;
			else
				errno = -errno;
		}
	} else
#endif
	if (scr->pt.r10 != -1) {
		/*
		 * A system calls has to be restarted only if one of the error codes
		 * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned.  If r10
		 * isn't -1 then r8 doesn't hold an error code and we don't need to
		 * restart the syscall, so we can clear the "restart" flag here.
		 */
		restart = 0;
	}

	for (;;) {
		unsigned long signr;

		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			current->thread.siginfo = &info;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();

			signr = current->exit_code;
			current->thread.siginfo = 0;

			/* We're back.  Did the debugger cancel the sig?  */
			if (!signr)
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr - 1];
		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			      case SIGCONT: case SIGCHLD: case SIGWINCH:
				continue;

			      case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;
				/* FALLTHRU */

			      case SIGSTOP:
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				sig = current->p_pptr->sig;
				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;

			      case SIGQUIT: case SIGILL: case SIGTRAP:
			      case SIGABRT: case SIGFPE: case SIGSEGV:
			      case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, &scr->pt))
					exit_code |= 0x80;
				/* FALLTHRU */

			      default:
				sigaddset(&current->pending.signal, signr);
				recalc_sigpending(current);
				current->flags |= PF_SIGNALED;
				do_exit(exit_code);
				/* NOTREACHED */
			}
		}

		if (restart) {
			switch (errno) {
			      case ERESTARTSYS:
				if ((ka->sa.sa_flags & SA_RESTART) == 0) {
			      case ERESTARTNOHAND:
#ifdef CONFIG_IA32_SUPPORT
					if (IS_IA32_PROCESS(&scr->pt))
						scr->pt.r8 = -EINTR;
					else
#endif
					scr->pt.r8 = EINTR;
					/* note: scr->pt.r10 is already -1 */
					break;
				}
			      case ERESTARTNOINTR:
#ifdef CONFIG_IA32_SUPPORT
				if (IS_IA32_PROCESS(&scr->pt)) {
					scr->pt.r8 = scr->pt.r1;
					scr->pt.cr_iip -= 2;
				} else
#endif
				ia64_decrement_ip(&scr->pt);
			}
		}

		/* Whee!  Actually deliver the signal.  If the
		   delivery failed, we need to continue to iterate in
		   this loop so we can deliver the SIGSEGV... */
		if (handle_signal(signr, ka, &info, oldset, scr))
			return 1;
	}

	/* Did we come from a system call? */
	if (restart) {
		/* Restart the system call - no handlers present */
		if (errno == ERESTARTNOHAND || errno == ERESTARTSYS || errno == ERESTARTNOINTR) {
#ifdef CONFIG_IA32_SUPPORT
			if (IS_IA32_PROCESS(&scr->pt)) {
				scr->pt.r8 = scr->pt.r1;
				scr->pt.cr_iip -= 2;
			} else
#endif
			/*
			 * Note: the syscall number is in r15 which is
			 * saved in pt_regs so all we need to do here
			 * is adjust ip so that the "break"
			 * instruction gets re-executed.
			 */
			ia64_decrement_ip(&scr->pt);
		}
	}
	return 0;
}
/* the heart of this library: the thread scheduler */
intern void *pth_scheduler(void *dummy)
{
    sigset_t sigs;
    pth_time_t running;
    pth_time_t snapshot;
    struct sigaction sa;
    sigset_t ss;
    int sig;
    pth_t t;

    /*
     * bootstrapping
     */
    pth_debug1("pth_scheduler: bootstrapping");

    /* mark this thread as the special scheduler thread */
    pth_sched->state = PTH_STATE_SCHEDULER;

    /* block all signals in the scheduler thread */
    sigfillset(&sigs);
    pth_sc(sigprocmask)(SIG_SETMASK, &sigs, NULL);

    /* initialize the snapshot time for bootstrapping the loop */
    pth_time_set(&snapshot, PTH_TIME_NOW);

    /*
     * endless scheduler loop
     */
    for (;;) {
        /*
         * Move threads from new queue to ready queue and optionally
         * give them maximum priority so they start immediately.
         */
        while ((t = pth_pqueue_tail(&pth_NQ)) != NULL) {
            pth_pqueue_delete(&pth_NQ, t);
            t->state = PTH_STATE_READY;
            if (pth_favournew)
                pth_pqueue_insert(&pth_RQ, pth_pqueue_favorite_prio(&pth_RQ), t);
            else
                pth_pqueue_insert(&pth_RQ, PTH_PRIO_STD, t);
            pth_debug2("pth_scheduler: new thread \"%s\" moved to top of ready queue", t->name);
        }
        
        /* Calculate thread target runtime for ready queue */
        pth_pqueue_calc_target(&pth_RQ); 

        /* Assign tikets to threads in ready queue */
        pth_pqueue_issue_tk(&pth_RQ);

        /*
         * Update average scheduler load
         */
        pth_scheduler_load(&snapshot);

        /*
         * Find next thread in ready queue
         */
        /* generate lottery number randomly */
        /* pth_current = pth_pqueue_delmax(&pth_RQ); */
        int ltr_num = rand() % pth_RQ.total_tk;
        pth_current = pth_pqueue_deltk(&pth_RQ, ltr_num); 
	  
        if (pth_current == NULL) {
            fprintf(stderr, "**Pth** SCHEDULER INTERNAL ERROR: "
                        "no more thread(s) available to schedule!?!?\n");
            abort();
        }
        pth_debug4("pth_scheduler: thread \"%s\" selected (prio=%d, qprio=%d)",
                   pth_current->name, pth_current->prio, pth_current->q_prio);

        /*
         * Raise additionally thread-specific signals
         * (they are delivered when we switch the context)
         *
         * Situation is ('#' = signal pending):
         *     process pending (pth_sigpending):         ----####
         *     thread pending (pth_current->sigpending): --##--##
         * Result has to be:
         *     process new pending:                      --######
         */
        if (pth_current->sigpendcnt > 0) {
            sigpending(&pth_sigpending);
            for (sig = 1; sig < PTH_NSIG; sig++)
                if (sigismember(&pth_current->sigpending, sig))
                    if (!sigismember(&pth_sigpending, sig))
                        kill(getpid(), sig);
        }

        /*
         * Set running start time for new thread
         * and perform a context switch to it
         */
        pth_debug3("pth_scheduler: switching to thread 0x%lx (\"%s\")",
                   (unsigned long)pth_current, pth_current->name);

        /* update thread times */
        pth_time_set(&pth_current->lastran, PTH_TIME_NOW);

        /* update scheduler times */
        pth_time_set(&running, &pth_current->lastran);
        pth_time_sub(&running, &snapshot);
        pth_time_add(&pth_sched->running, &running);    
 
        /* ** ENTERING THREAD ** - by switching the machine context */
        pth_current->dispatches++;
        pth_mctx_switch(&pth_sched->mctx, &pth_current->mctx);

        /* update scheduler times */
        pth_time_set(&snapshot, PTH_TIME_NOW);
        pth_debug3("pth_scheduler: cameback from thread 0x%lx (\"%s\")",
                   (unsigned long)pth_current, pth_current->name);

        /*
         * Calculate and update the time the previous thread was running
         */
        pth_time_set(&running, &snapshot);
        pth_time_sub(&running, &pth_current->lastran);
        pth_time_add(&pth_current->running, &running);

        /* Update actual time of all threads in ready queue */
        pth_pqueue_update_a_rt(&pth_RQ);
        
        pth_debug3("pth_scheduler: thread \"%s\" ran %.6f",
                   pth_current->name, pth_time_t2d(&running));
        /* Additional debugging code */
        pth_debug2("pth_scheduler: lottery number %d",
                   ltr_num);
        pth_debug2("pth_scheduler: total ticket %d",
                   pth_RQ.total_tk);
        pth_debug3("pth_scheduler: thread has %d offset and %d tickets",
                   (pth_current->tk).offset, (pth_current->tk).tk_num);
        pth_debug3("pth_scheduler: thread has %.6f running time and %.6f lifetime",
                   pth_time_t2d(&pth_current->running), pth_time_t2d(&lifetime));
        pth_debug2("pth_scheduler: thread has %.6f target runtime",
                   (pth_current->cpu_rt).target);
        pth_debug2("pth_scheduler: thread has %.6f actual runtime",
                   (pth_current->cpu_rt).actual);
        
        
        /*
         * Remove still pending thread-specific signals
         * (they are re-delivered next time)
         *
         * Situation is ('#' = signal pending):
         *     thread old pending (pth_current->sigpending): --##--##
         *     process old pending (pth_sigpending):         ----####
         *     process still pending (sigstillpending):      ---#-#-#
         * Result has to be:
         *     process new pending:                          -----#-#
         *     thread new pending (pth_current->sigpending): ---#---#
         */
        if (pth_current->sigpendcnt > 0) {
            sigset_t sigstillpending;
            sigpending(&sigstillpending);
            for (sig = 1; sig < PTH_NSIG; sig++) {
                if (sigismember(&pth_current->sigpending, sig)) {
                    if (!sigismember(&sigstillpending, sig)) {
                        /* thread (and perhaps also process) signal delivered */
                        sigdelset(&pth_current->sigpending, sig);
                        pth_current->sigpendcnt--;
                    }
                    else if (!sigismember(&pth_sigpending, sig)) {
                        /* thread signal not delivered */
                        pth_util_sigdelete(sig);
                    }
                }
            }
        }

        /*
         * Check for stack overflow
         */
        if (pth_current->stackguard != NULL) {
            if (*pth_current->stackguard != 0xDEAD) {
                pth_debug3("pth_scheduler: stack overflow detected for thread 0x%lx (\"%s\")",
                           (unsigned long)pth_current, pth_current->name);
                /*
                 * if the application doesn't catch SIGSEGVs, we terminate
                 * manually with a SIGSEGV now, but output a reasonable message.
                 */
                if (sigaction(SIGSEGV, NULL, &sa) == 0) {
                    if (sa.sa_handler == SIG_DFL) {
                        fprintf(stderr, "**Pth** STACK OVERFLOW: thread pid_t=0x%lx, name=\"%s\"\n",
                                (unsigned long)pth_current, pth_current->name);
                        kill(getpid(), SIGSEGV);
                        sigfillset(&ss);
                        sigdelset(&ss, SIGSEGV);
                        sigsuspend(&ss);
                        abort();
                    }
                }
                /*
                 * else we terminate the thread only and send us a SIGSEGV
                 * which allows the application to handle the situation...
                 */
                pth_current->join_arg = (void *)0xDEAD;
                pth_current->state = PTH_STATE_DEAD;
                kill(getpid(), SIGSEGV);
            }
        }

        /*
         * If previous thread is now marked as dead, kick it out
         */
        if (pth_current->state == PTH_STATE_DEAD) {
            pth_debug2("pth_scheduler: marking thread \"%s\" as dead", pth_current->name);
            if (!pth_current->joinable)
                pth_tcb_free(pth_current);
            else
                pth_pqueue_insert(&pth_DQ, PTH_PRIO_STD, pth_current);
            pth_current = NULL;
        }

        /*
         * If thread wants to wait for an event
         * move it to waiting queue now
         */
        if (pth_current != NULL && pth_current->state == PTH_STATE_WAITING) {
            pth_debug2("pth_scheduler: moving thread \"%s\" to waiting queue",
                       pth_current->name);
            pth_pqueue_insert(&pth_WQ, pth_current->prio, pth_current);
            pth_current = NULL;
        }

        /*
         * migrate old treads in ready queue into higher
         * priorities to avoid starvation and insert last running
         * thread back into this queue, too.
         */
	/* Disable this auto-increment mechanism */
        /* pth_pqueue_increase(&pth_RQ); */
        if (pth_current != NULL)
            pth_pqueue_insert(&pth_RQ, pth_current->prio, pth_current);

        /*
         * Manage the events in the waiting queue, i.e. decide whether their
         * events occurred and move them to the ready queue. But wait only if
         * we have already no new or ready threads.
         */
        if (   pth_pqueue_elements(&pth_RQ) == 0
            && pth_pqueue_elements(&pth_NQ) == 0)
            /* still no NEW or READY threads, so we have to wait for new work */
            pth_sched_eventmanager(&snapshot, FALSE /* wait */);
        else
            /* already NEW or READY threads exists, so just poll for even more work */
            pth_sched_eventmanager(&snapshot, TRUE  /* poll */);
    }

    /* NOTREACHED */
    return NULL;
}
Beispiel #28
0
char *
print_arg(struct syscall_args *sc, unsigned long *args, long retval,
    struct trussinfo *trussinfo)
{
	char *tmp;
	pid_t pid;

	tmp = NULL;
	pid = trussinfo->pid;
	switch (sc->type & ARG_MASK) {
	case Hex:
		asprintf(&tmp, "0x%x", (int)args[sc->offset]);
		break;
	case Octal:
		asprintf(&tmp, "0%o", (int)args[sc->offset]);
		break;
	case Int:
		asprintf(&tmp, "%d", (int)args[sc->offset]);
		break;
	case Name: {
		/* NULL-terminated string. */
		char *tmp2;
		tmp2 = get_string(pid, (void*)args[sc->offset], 0);
		asprintf(&tmp, "\"%s\"", tmp2);
		free(tmp2);
		break;
	}
	case BinString: {
		/* Binary block of data that might have printable characters.
		   XXX If type|OUT, assume that the length is the syscall's
		   return value.  Otherwise, assume that the length of the block
		   is in the next syscall argument. */
		int max_string = trussinfo->strsize;
		char tmp2[max_string+1], *tmp3;
		int len;
		int truncated = 0;

		if (sc->type & OUT)
			len = retval;
		else
			len = args[sc->offset + 1];

		/* Don't print more than max_string characters, to avoid word
		   wrap.  If we have to truncate put some ... after the string.
		*/
		if (len > max_string) {
			len = max_string;
			truncated = 1;
		}
		if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
		    != -1) {
			tmp3 = malloc(len * 4 + 1);
			while (len) {
				if (strvisx(tmp3, tmp2, len,
				    VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
					break;
				len--;
				truncated = 1;
			};
			asprintf(&tmp, "\"%s\"%s", tmp3, truncated ?
			    "..." : "");
			free(tmp3);
		} else {
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		}
		break;
	}
	case StringArray: {
		int num, size, i;
		char *tmp2;
		char *string;
		char *strarray[100];	/* XXX This is ugly. */

		if (get_struct(pid, (void *)args[sc->offset],
		    (void *)&strarray, sizeof(strarray)) == -1)
			err(1, "get_struct %p", (void *)args[sc->offset]);
		num = 0;
		size = 0;

		/* Find out how large of a buffer we'll need. */
		while (strarray[num] != NULL) {
			string = get_string(pid, (void*)strarray[num], 0);
			size += strlen(string);
			free(string);
			num++;
		}
		size += 4 + (num * 4);
		tmp = (char *)malloc(size);
		tmp2 = tmp;

		tmp2 += sprintf(tmp2, " [");
		for (i = 0; i < num; i++) {
			string = get_string(pid, (void*)strarray[i], 0);
			tmp2 += sprintf(tmp2, " \"%s\"%c", string,
			    (i + 1 == num) ? ' ' : ',');
			free(string);
		}
		tmp2 += sprintf(tmp2, "]");
		break;
	}
#ifdef __LP64__
	case Quad:
		asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
#else
	case Quad: {
		unsigned long long ll;
		ll = *(unsigned long long *)(args + sc->offset);
		asprintf(&tmp, "0x%llx", ll);
		break;
	}
#endif
	case Ptr:
		asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	case Readlinkres: {
		char *tmp2;
		if (retval == -1) {
			tmp = strdup("");
			break;
		}
		tmp2 = get_string(pid, (void*)args[sc->offset], retval);
		asprintf(&tmp, "\"%s\"", tmp2);
		free(tmp2);
		break;
	}
	case Ioctl: {
		const char *temp = ioctlname(args[sc->offset]);
		if (temp)
			tmp = strdup(temp);
		else {
			unsigned long arg = args[sc->offset];
			asprintf(&tmp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
			    arg, arg & IOC_OUT ? "R" : "",
			    arg & IOC_IN ? "W" : "", IOCGROUP(arg),
			    isprint(IOCGROUP(arg)) ? (char)IOCGROUP(arg) : '?',
			    arg & 0xFF, IOCPARM_LEN(arg));
		}
		break;
	}
	case Umtx: {
		struct umtx umtx;
		if (get_struct(pid, (void *)args[sc->offset], &umtx,
		    sizeof(umtx)) != -1)
			asprintf(&tmp, "{ 0x%lx }", (long)umtx.u_owner);
		else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case Timespec: {
		struct timespec ts;
		if (get_struct(pid, (void *)args[sc->offset], &ts,
		    sizeof(ts)) != -1)
			asprintf(&tmp, "{%ld.%09ld }", (long)ts.tv_sec,
			    ts.tv_nsec);
		else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case Timeval: {
		struct timeval tv;
		if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
		    != -1)
			asprintf(&tmp, "{%ld.%06ld }", (long)tv.tv_sec,
			    tv.tv_usec);
		else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case Timeval2: {
		struct timeval tv[2];
		if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
		    != -1)
			asprintf(&tmp, "{%ld.%06ld, %ld.%06ld }",
			    (long)tv[0].tv_sec, tv[0].tv_usec,
			    (long)tv[1].tv_sec, tv[1].tv_usec);
		else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case Itimerval: {
		struct itimerval itv;
		if (get_struct(pid, (void *)args[sc->offset], &itv,
		    sizeof(itv)) != -1)
			asprintf(&tmp, "{%ld.%06ld, %ld.%06ld }",
			    (long)itv.it_interval.tv_sec,
			    itv.it_interval.tv_usec,
			    (long)itv.it_value.tv_sec,
			    itv.it_value.tv_usec);
		else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case LinuxSockArgs:
	{
		struct linux_socketcall_args largs;
		if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
		    sizeof(largs)) == -1) {
			err(1, "get_struct %p", (void *)args[sc->offset]);
		}
		const char *what;
		char buf[30];

		switch (largs.what) {
		case LINUX_SOCKET:
			what = "LINUX_SOCKET";
			break;
		case LINUX_BIND:
			what = "LINUX_BIND";
			break;
		case LINUX_CONNECT:
			what = "LINUX_CONNECT";
			break;
		case LINUX_LISTEN:
			what = "LINUX_LISTEN";
			break;
		case LINUX_ACCEPT:
			what = "LINUX_ACCEPT";
			break;
		case LINUX_GETSOCKNAME:
			what = "LINUX_GETSOCKNAME";
			break;
		case LINUX_GETPEERNAME:
			what = "LINUX_GETPEERNAME";
			break;
		case LINUX_SOCKETPAIR:
			what = "LINUX_SOCKETPAIR";
			break;
		case LINUX_SEND:   
			what = "LINUX_SEND";
			break;
		case LINUX_RECV: 
			what = "LINUX_RECV";
			break;
		case LINUX_SENDTO:
			what = "LINUX_SENDTO";
			break;
		case LINUX_RECVFROM:
			what = "LINUX_RECVFROM";
			break;
		case LINUX_SHUTDOWN:
			what = "LINUX_SHUTDOWN";
			break;
		case LINUX_SETSOCKOPT:
			what = "LINUX_SETSOCKOPT";
			break;
		case LINUX_GETSOCKOPT:
			what = "LINUX_GETSOCKOPT";
			break;
		case LINUX_SENDMSG:
			what = "LINUX_SENDMSG";
			break;
		case LINUX_RECVMSG:
			what = "LINUX_RECVMSG";
			break;
		default:
			sprintf(buf, "%d", largs.what);
			what = buf;
			break;
		}
		asprintf(&tmp, "(0x%lx)%s, 0x%lx", args[sc->offset], what, (long unsigned int)largs.args);
		break;
	}
	case Pollfd: {
		/*
		 * XXX: A Pollfd argument expects the /next/ syscall argument
		 * to be the number of fds in the array. This matches the poll
		 * syscall.
		 */
		struct pollfd *pfd;
		int numfds = args[sc->offset+1];
		int bytes = sizeof(struct pollfd) * numfds;
		int i, tmpsize, u, used;
		const int per_fd = 100;

		if ((pfd = malloc(bytes)) == NULL)
			err(1, "Cannot malloc %d bytes for pollfd array",
			    bytes);
		if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
		    != -1) {
			used = 0;
			tmpsize = 1 + per_fd * numfds + 2;
			if ((tmp = malloc(tmpsize)) == NULL)
				err(1, "Cannot alloc %d bytes for poll output",
				    tmpsize);

			tmp[used++] = '{';
			for (i = 0; i < numfds; i++) {

				u = snprintf(tmp + used, per_fd, "%s%d/%s",
				    i > 0 ? " " : "", pfd[i].fd,
				    xlookup_bits(poll_flags, pfd[i].events));
				if (u > 0)
					used += u < per_fd ? u : per_fd;
			}
			tmp[used++] = '}';
			tmp[used++] = '\0';
		} else {
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		}
		free(pfd);
		break;
	}
	case Fd_set: {
		/*
		 * XXX: A Fd_set argument expects the /first/ syscall argument
		 * to be the number of fds in the array.  This matches the
		 * select syscall.
		 */
		fd_set *fds;
		int numfds = args[0];
		int bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
		int i, tmpsize, u, used;
		const int per_fd = 20;

		if ((fds = malloc(bytes)) == NULL)
			err(1, "Cannot malloc %d bytes for fd_set array",
			    bytes);
		if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
		    != -1) {
			used = 0;
			tmpsize = 1 + numfds * per_fd + 2;
			if ((tmp = malloc(tmpsize)) == NULL)
				err(1, "Cannot alloc %d bytes for fd_set "
				    "output", tmpsize);

			tmp[used++] = '{';
			for (i = 0; i < numfds; i++) {
				if (FD_ISSET(i, fds)) {
					u = snprintf(tmp + used, per_fd, "%d ",
					    i);
					if (u > 0)
						used += u < per_fd ? u : per_fd;
				}
			}
			if (tmp[used-1] == ' ')
				used--;
			tmp[used++] = '}';
			tmp[used++] = '\0';
		} else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		free(fds);
		break;
	}
	case Signal:
		tmp = strsig2(args[sc->offset]);
		break;
	case Sigset: {
		long sig;
		sigset_t ss;
		int i, used;
		char *signame;

		sig = args[sc->offset];
		if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
		    sizeof(ss)) == -1) {
			asprintf(&tmp, "0x%lx", args[sc->offset]);
			break;
		}
		tmp = malloc(sys_nsig * 8); /* 7 bytes avg per signal name */
		used = 0;
		for (i = 1; i < sys_nsig; i++) {
			if (sigismember(&ss, i)) {
				signame = strsig(i);
				used += sprintf(tmp + used, "%s|", signame);
				free(signame);
			}
		}
		if (used)
			tmp[used-1] = 0;
		else
			strcpy(tmp, "0x0");
		break;
	}
	case Sigprocmask: {
		switch (args[sc->offset]) {
#define	S(a)	case a: tmp = strdup(#a); break;
			S(SIG_BLOCK);
			S(SIG_UNBLOCK);
			S(SIG_SETMASK);
#undef S
		}
		if (tmp == NULL)
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case Fcntlflag: {
		/* XXX output depends on the value of the previous argument */
		switch (args[sc->offset-1]) {
		case F_SETFD:
			tmp = strdup(xlookup_bits(fcntlfd_arg,
			    args[sc->offset]));
			break;
		case F_SETFL:
			tmp = strdup(xlookup_bits(fcntlfl_arg,
			    args[sc->offset]));
			break;
		case F_GETFD:
		case F_GETFL:
		case F_GETOWN:
			tmp = strdup("");
			break;
		default:
			asprintf(&tmp, "0x%lx", args[sc->offset]);
			break;
		}
		break;
	}
	case Open:
		tmp = strdup(xlookup_bits(open_flags, args[sc->offset]));
		break;
	case Fcntl:
		tmp = strdup(xlookup(fcntl_arg, args[sc->offset]));
		break;
	case Mprot:
		tmp = strdup(xlookup_bits(mprot_flags, args[sc->offset]));
		break;
	case Mmapflags: {
		char *base, *alignstr;
		int align, flags;

		/*
		 * MAP_ALIGNED can't be handled by xlookup_bits(), so
		 * generate that string manually and prepend it to the
		 * string from xlookup_bits().  Have to be careful to
		 * avoid outputting MAP_ALIGNED|0 if MAP_ALIGNED is
		 * the only flag.
		 */
		flags = args[sc->offset] & ~MAP_ALIGNMENT_MASK;
		align = args[sc->offset] & MAP_ALIGNMENT_MASK;
		if (align != 0) {
			if (align == MAP_ALIGNED_SUPER)
				alignstr = strdup("MAP_ALIGNED_SUPER");
			else
				asprintf(&alignstr, "MAP_ALIGNED(%d)",
				    align >> MAP_ALIGNMENT_SHIFT);
			if (flags == 0) {
				tmp = alignstr;
				break;
			}
		} else
			alignstr = NULL;
		base = strdup(xlookup_bits(mmap_flags, flags));
		if (alignstr == NULL) {
			tmp = base;
			break;
		}
		asprintf(&tmp, "%s|%s", alignstr, base);
		free(alignstr);
		free(base);
		break;
	}
	case Whence:
		tmp = strdup(xlookup(whence_arg, args[sc->offset]));
		break;
	case Sockdomain:
		tmp = strdup(xlookup(sockdomain_arg, args[sc->offset]));
		break;
	case Socktype:
		tmp = strdup(xlookup(socktype_arg, args[sc->offset]));
		break;
	case Shutdown:
		tmp = strdup(xlookup(shutdown_arg, args[sc->offset]));
		break;
	case Resource:
		tmp = strdup(xlookup(resource_arg, args[sc->offset]));
		break;
	case Pathconf:
		tmp = strdup(xlookup(pathconf_arg, args[sc->offset]));
		break;
	case Rforkflags:
		tmp = strdup(xlookup_bits(rfork_flags, args[sc->offset]));
		break;
	case Sockaddr: {
		struct sockaddr_storage ss;
		char addr[64];
		struct sockaddr_in *lsin;
		struct sockaddr_in6 *lsin6;
		struct sockaddr_un *sun;
		struct sockaddr *sa;
		char *p;
		u_char *q;
		int i;

		if (args[sc->offset] == 0) {
			asprintf(&tmp, "NULL");
			break;
		}

		/* yuck: get ss_len */
		if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
		    sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1)
			err(1, "get_struct %p", (void *)args[sc->offset]);
		/*
		 * If ss_len is 0, then try to guess from the sockaddr type.
		 * AF_UNIX may be initialized incorrectly, so always frob
		 * it by using the "right" size.
		 */
		if (ss.ss_len == 0 || ss.ss_family == AF_UNIX) {
			switch (ss.ss_family) {
			case AF_INET:
				ss.ss_len = sizeof(*lsin);
				break;
			case AF_UNIX:
				ss.ss_len = sizeof(*sun);
				break;
			default:
				/* hurrrr */
				break;
			}
		}
		if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
		    ss.ss_len) == -1) {
			err(2, "get_struct %p", (void *)args[sc->offset]);
		}

		switch (ss.ss_family) {
		case AF_INET:
			lsin = (struct sockaddr_in *)&ss;
			inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof addr);
			asprintf(&tmp, "{ AF_INET %s:%d }", addr,
			    htons(lsin->sin_port));
			break;
		case AF_INET6:
			lsin6 = (struct sockaddr_in6 *)&ss;
			inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
			    sizeof addr);
			asprintf(&tmp, "{ AF_INET6 [%s]:%d }", addr,
			    htons(lsin6->sin6_port));
			break;
		case AF_UNIX:
			sun = (struct sockaddr_un *)&ss;
			asprintf(&tmp, "{ AF_UNIX \"%s\" }", sun->sun_path);
			break;
		default:
			sa = (struct sockaddr *)&ss;
			asprintf(&tmp, "{ sa_len = %d, sa_family = %d, sa_data "
			    "= {%n%*s } }", (int)sa->sa_len, (int)sa->sa_family,
			    &i, 6 * (int)(sa->sa_len - ((char *)&sa->sa_data -
			    (char *)sa)), "");
			if (tmp != NULL) {
				p = tmp + i;
				for (q = (u_char *)&sa->sa_data;
				    q < (u_char *)sa + sa->sa_len; q++)
					p += sprintf(p, " %#02x,", *q);
			}
		}
		break;
	}
	case Sigaction: {
		struct sigaction sa;
		char *hand;
		const char *h;

		if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
		    != -1) {
			asprintf(&hand, "%p", sa.sa_handler);
			if (sa.sa_handler == SIG_DFL)
				h = "SIG_DFL";
			else if (sa.sa_handler == SIG_IGN)
				h = "SIG_IGN";
			else
				h = hand;

			asprintf(&tmp, "{ %s %s ss_t }", h,
			    xlookup_bits(sigaction_flags, sa.sa_flags));
			free(hand);
		} else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case Kevent: {
		/*
		 * XXX XXX: the size of the array is determined by either the
		 * next syscall argument, or by the syscall returnvalue,
		 * depending on which argument number we are.  This matches the
		 * kevent syscall, but luckily that's the only syscall that uses
		 * them.
		 */
		struct kevent *ke;
		int numevents = -1;
		int bytes = 0;
		int i, tmpsize, u, used;
		const int per_ke = 100;

		if (sc->offset == 1)
			numevents = args[sc->offset+1];
		else if (sc->offset == 3 && retval != -1)
			numevents = retval;

		if (numevents >= 0)
			bytes = sizeof(struct kevent) * numevents;
		if ((ke = malloc(bytes)) == NULL)
			err(1, "Cannot malloc %d bytes for kevent array",
			    bytes);
		if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
		    ke, bytes) != -1) {
			used = 0;
			tmpsize = 1 + per_ke * numevents + 2;
			if ((tmp = malloc(tmpsize)) == NULL)
				err(1, "Cannot alloc %d bytes for kevent "
				    "output", tmpsize);

			tmp[used++] = '{';
			for (i = 0; i < numevents; i++) {
				u = snprintf(tmp + used, per_ke,
				    "%s%p,%s,%s,%d,%p,%p",
				    i > 0 ? " " : "",
				    (void *)ke[i].ident,
				    xlookup(kevent_filters, ke[i].filter),
				    xlookup_bits(kevent_flags, ke[i].flags),
				    ke[i].fflags,
				    (void *)ke[i].data,
				    (void *)ke[i].udata);
				if (u > 0)
					used += u < per_ke ? u : per_ke;
			}
			tmp[used++] = '}';
			tmp[used++] = '\0';
		} else {
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		}
		free(ke);
		break;
	}
	case Stat: {
		struct stat st;
		if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
		    != -1) {
			char mode[12];
			strmode(st.st_mode, mode);
			asprintf(&tmp,
			    "{ mode=%s,inode=%jd,size=%jd,blksize=%ld }", mode,
			    (intmax_t)st.st_ino, (intmax_t)st.st_size,
			    (long)st.st_blksize);
		} else {
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		}
		break;
	}
	case Rusage: {
		struct rusage ru;
		if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
		    != -1) {
			asprintf(&tmp,
			    "{ u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld }",
			    (long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
			    (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
			    ru.ru_inblock, ru.ru_oublock);
		} else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case Rlimit: {
		struct rlimit rl;
		if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
		    != -1) {
			asprintf(&tmp, "{ cur=%ju,max=%ju }",
			    rl.rlim_cur, rl.rlim_max);
		} else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		break;
	}
	case ExitStatus: {
		char *signame;
		int status;
		signame = NULL;
		if (get_struct(pid, (void *)args[sc->offset], &status,
		    sizeof(status)) != -1) {
			if (WIFCONTINUED(status))
				tmp = strdup("{ CONTINUED }");
			else if (WIFEXITED(status))
				asprintf(&tmp, "{ EXITED,val=%d }",
				    WEXITSTATUS(status));
			else if (WIFSIGNALED(status))
				asprintf(&tmp, "{ SIGNALED,sig=%s%s }",
				    signame = strsig2(WTERMSIG(status)),
				    WCOREDUMP(status) ? ",cored" : "");
			else
				asprintf(&tmp, "{ STOPPED,sig=%s }",
				    signame = strsig2(WTERMSIG(status)));
		} else
			asprintf(&tmp, "0x%lx", args[sc->offset]);
		free(signame);
		break;
	}
	case Waitoptions:
		tmp = strdup(xlookup_bits(wait_options, args[sc->offset]));
		break;
	case Idtype:
		tmp = strdup(xlookup(idtype_arg, args[sc->offset]));
		break;
	case Procctl:
		tmp = strdup(xlookup(procctl_arg, args[sc->offset]));
		break;
	default:
		errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
	}
/* Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 */
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
			 unsigned long orig_i0, int restart_syscall)
{
	unsigned long signr;
	siginfo_t info;
	struct k_sigaction *ka;
	
	if (!oldset)
		oldset = &current->blocked;

#ifdef CONFIG_SPARC32_COMPAT
	if (current->thread.flags & SPARC_FLAG_32BIT) {
		extern asmlinkage int do_signal32(sigset_t *, struct pt_regs *,
						  unsigned long, int);
		return do_signal32(oldset, regs, orig_i0, restart_syscall);
	}
#endif	
	for (;;) {
		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);
		
		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Do the syscall restart before we let the debugger
			 * look at the child registers.
			 */
			if (restart_syscall &&
			    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
			     regs->u_regs[UREG_I0] == ERESTARTSYS ||
			     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
				regs->u_regs[UREG_I0] = orig_i0;
				regs->tpc -= 4;
				regs->tnpc -= 4;
				restart_syscall = 0;
			}

			current->exit_code = signr;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();
			if (!(signr = current->exit_code))
				continue;
			current->exit_code = 0;
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}
		
		ka = &current->sig->action[signr-1];
		
		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;

                        /* sys_wait4() grabs the master kernel lock, so
                         * we need not do so, that sucker should be
                         * threaded and would not be that difficult to
                         * do anyways.
                         */
                        while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
                                ;
			continue;
		}
		if (ka->sa.sa_handler == SIG_DFL) {
			unsigned long exit_code = signr;
			
			if (current->pid == 1)
				continue;
			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;

			case SIGSTOP:
				if (current->ptrace & PT_PTRACED)
					continue;
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
				      SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
#ifdef DEBUG_SIGNALS
				/* Very useful to debug the dynamic linker */
				printk ("Sig %d going...\n", (int)signr);
				show_regs (regs);
#ifdef DEBUG_SIGNALS_TRACE
				{
					struct reg_window *rw = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
					unsigned long ins[8];
                                                
					while (rw &&
					       !(((unsigned long) rw) & 0x3)) {
					        copy_from_user(ins, &rw->ins[0], sizeof(ins));
						printk("Caller[%016lx](%016lx,%016lx,%016lx,%016lx,%016lx,%016lx)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]);
						rw = (struct reg_window *)(unsigned long)(ins[6] + STACK_BIAS);
					}
				}
#endif			
#ifdef DEBUG_SIGNALS_MAPS	
				printk("Maps:\n");
				read_maps();
#endif
#endif
				/* fall through */
			default:
				sig_exit(signr, exit_code, &info);
				/* NOT REACHED */
			}
		}
		if (restart_syscall)
			syscall_restart(orig_i0, regs, &ka->sa);
		handle_signal(signr, ka, &info, oldset, regs);
		return 1;
	}
	if (restart_syscall &&
	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
	     regs->u_regs[UREG_I0] == ERESTARTSYS ||
	     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
		/* replay the system call when we are done */
		regs->u_regs[UREG_I0] = orig_i0;
		regs->tpc -= 4;
		regs->tnpc -= 4;
	}
	return 0;
}
Beispiel #30
0
/* Set up all the radvd internal stuff from our own configuration */
int radvd_init(char *ifname, struct config *c) {
  struct AdvPrefix *prefix;
  sigset_t oset, nset;


  if (log_open(L_STDERR, "radvd", NULL, -1) < 0) {
    error("log_open\n");
    return -1;
  }
  srand((unsigned int)time(NULL));
  info("starting radvd on device %s\n", ifname);

  sock = open_icmpv6_socket();
  if (sock < 0) {
    error("open_icmpv6_socket\n");
    return -1;
  }
  sigemptyset(&nset);
  sigaddset(&nset, SIGALRM);
  sigprocmask(SIG_UNBLOCK, &nset, &oset);
  if (sigismember(&oset, SIGALRM))
    flog(LOG_WARNING, "SIGALRM has been unblocked. Your startup environment might be wrong.");


  /* setup the radvd struct Interface to know about all our defaults */
  iface = malloc(sizeof(struct Interface));
  if (iface == NULL)
    return -1;

  iface_init_defaults(iface);
  strncpy(iface->Name, ifname, IFNAMSIZ-1);
  iface->Name[IFNAMSIZ-1] = '\0';

  iface->next = NULL;
  iface->AdvSendAdvert = 1;

  /* check the interface exists... this probably shouldn't fail */
  if (check_device(sock, iface) < 0) {
    error("check_device!\n");
    return -1;
  }
  
  if (setup_deviceinfo(sock, iface) < 0) {
    error("setup_deviceinfo\n");
    return -1;
  }
  if (check_iface(iface) < 0) {
    error("check_iface\n");
    return -1;
  }
  if (setup_linklocal_addr(sock, iface) < 0) {
    error("setup_linklocal_addr\n");
    return -1;
  }
  if (setup_allrouters_membership(sock, iface) < 0) {
    error("setup_allrouters_membership\n");
    return -1;
  }


  /* set up the prefix we're advertising from the config struct we get passed in. */
  prefix = malloc(sizeof(struct AdvPrefix));
  if (prefix == NULL)
    return -1;

  prefix_init_defaults(prefix);
  prefix->PrefixLen = 64;
  memcpy(&prefix->Prefix, c->router_addr.s6_addr, sizeof(struct in6_addr));
  prefix->next = NULL;

  iface->AdvPrefixList = prefix;


  // config_interface();
  radvd_kickoff_adverts();

  set_debuglevel(0);

  return sock;
}