Пример #1
0
int main(void)
{
    char buf[1024];
    
    sig2str(SIGINT, buf);
    sig2str(SIGALRM, buf);
}
Пример #2
0
static int
display_stack_info(uintptr_t pc, int signo, void *arg)
{

	char buffer[MAX_LINE];
	char sigbuf[SIG2STR_MAX];


	int filenum = (intptr_t)arg;

	(void) addrtosymstr((void *)pc, buffer, sizeof (buffer));

	if (signo) {
		sigbuf[0] = '?';
		sigbuf[1] = 0;

		(void) sig2str(signo, sigbuf);

		async_filenoprintf(filenum, "%s [Signal %d (%s)]\n",
		    buffer, (ulong_t)signo, sigbuf);
	} else
		async_filenoprintf(filenum, "%s\n", buffer);

	return (0);
}
Пример #3
0
extern int
operand2sig (char const *operand, char *signame)
{
  int signum;

  if (ISDIGIT (*operand))
    {
      /* Note we don't put a limit on the maximum value passed,
         because we're checking shell $? values here, and ksh for
         example will add 256 to the signal value, thus being wider
         than the number of WEXITSTATUS bits.
         We could validate that values were not above say
         ((WEXITSTATUS (~0) << 1) + 1), which would cater for ksh.
         But some shells may use other adjustments in future to be
         (forward) compatible with systems that support
         wider exit status values as discussed at
         http://austingroupbugs.net/view.php?id=947  */

      char *endp;
      long int l = (errno = 0, strtol (operand, &endp, 10));
      int i = l;
      signum = (operand == endp || *endp || errno || i != l ? -1 : i);

      if (signum != -1)
        {
          /* Note AIX uses a different bit pattern for status returned
             from shell and wait(), so we can't use WTERMSIG etc. here.
             Also ksh returns 0xFF + signal number.  */
          signum &= signum >= 0xFF ? 0xFF : 0x7F;
        }
    }
  else
    {
      /* Convert signal to upper case in the C locale, not in the
         current locale.  Don't assume ASCII; it might be EBCDIC.  */
      char *upcased = xstrdup (operand);
      char *p;
      for (p = upcased; *p; p++)
        if (strchr ("abcdefghijklmnopqrstuvwxyz", *p))
          *p += 'A' - 'a';

      /* Look for the signal name, possibly prefixed by "SIG",
         and possibly lowercased.  */
      if (!(str2sig (upcased, &signum) == 0
            || (upcased[0] == 'S' && upcased[1] == 'I' && upcased[2] == 'G'
                && str2sig (upcased + 3, &signum) == 0)))
        signum = -1;

      free (upcased);
    }

  if (signum < 0 || sig2str (signum, signame) != 0)
    {
      error (0, 0, _("%s: invalid signal"), quote (operand));
      return -1;
    }

  return signum;
}
Пример #4
0
void
prsigset(FILE *fp, sigset_t *set)
{
	int i;
	char signame[SIG2STR_MAX];

	for (i = 1; i <= MAXSIG; i++) {
		sig2str(i, signame);
		(void) fprintf(fp, "%d  SIG%s\n", sigismember(set, i), signame);
	}
}
static void
sig_usr(int signo)
{
	char *str;
	str = malloc(sizeof(char) * 100);
	if (signo == SIGUSR1)
		printf("received SIGUSR1\n");
	else if (signo == SIGUSR2)
		printf("received SIGUSR2\n");
	else
		err_dump("received signal %d\n", signo);
	sig2str(&str, &signo);
	printf("%s\n", str);
}
Пример #6
0
/* Called for each frame on the stack to print it's contents */
static int
xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
{
    Dl_info dlinfo;
    ElfSym *dlsym;
    char header[32];
    int depth = *((int *) arg);

    if (signo) {
        char signame[SIG2STR_MAX];

        if (sig2str(signo, signame) != 0) {
            strcpy(signame, "unknown");
        }

        ErrorFSigSafe("** Signal %u (%s)\n", signo, signame);
    }

    snprintf(header, sizeof(header), "%d: 0x%lx", depth, pc);
    *((int *) arg) = depth + 1;

    /* Ask system dynamic loader for info on the address */
    if (dladdr1((void *) pc, &dlinfo, (void **) &dlsym, RTLD_DL_SYMENT)) {
        unsigned long offset = pc - (uintptr_t) dlinfo.dli_saddr;
        const char *symname;

        if (offset < dlsym->st_size) {  /* inside a function */
            symname = dlinfo.dli_sname;
        }
        else {                  /* found which file it was in, but not which function */
            symname = "<section start>";
            offset = pc - (uintptr_t) dlinfo.dli_fbase;
        }
        ErrorFSigSafe("%s: %s:%s+0x%x\n", header, dlinfo.dli_fname, symname,
                      offset);

    }
    else {
        /* Couldn't find symbol info from system dynamic loader, should
         * probably poke elfloader here, but haven't written that code yet,
         * so we just print the pc.
         */
        ErrorFSigSafe("%s\n", header);
    }

    return 0;
}
Пример #7
0
static void
cleanup (int sig)
{
  if (sig == SIGALRM)
    {
      timed_out = 1;
      sig = term_signal;
    }
  if (monitored_pid)
    {
      if (kill_after)
        {
          int saved_errno = errno; /* settimeout may reset.  */
          /* Start a new timeout after which we'll send SIGKILL.  */
          term_signal = SIGKILL;
          settimeout (kill_after, false);
          kill_after = 0; /* Don't let later signals reset kill alarm.  */
          errno = saved_errno;
        }

      /* Send the signal directly to the monitored child,
         in case it has itself become group leader,
         or is not running in a separate group.  */
      if (verbose)
        {
          char signame[MAX (SIG2STR_MAX, INT_BUFSIZE_BOUND (int))];
          if (sig2str (sig, signame) != 0)
            snprintf (signame, sizeof signame, "%d", sig);
          error (0, 0, _("sending signal %s to command %s"),
                 signame, quote (command));
        }
      send_sig (monitored_pid, sig);

      /* The normal case is the job has remained in our
         newly created process group, so send to all processes in that.  */
      if (!foreground)
        {
          send_sig (0, sig);
          if (sig != SIGKILL && sig != SIGCONT)
            {
              send_sig (monitored_pid, SIGCONT);
              send_sig (0, SIGCONT);
            }
        }
    }
  else /* we're the child or the child is not exec'd yet.  */
Пример #8
0
static void
print_exit_status(pid_t pid, int wstat)
{
	(void) printf("%d: ", (int)pid);
	if (WIFSIGNALED(wstat)) {
		char buf[SIG2STR_MAX];
		int sig = WTERMSIG(wstat);

		if (sig2str(sig, buf) == 0)
			(void) printf("killed by signal %s", buf);
		else
			(void) printf("killed by signal %d", sig);

		if (WCOREDUMP(wstat))
			(void) printf(" (core dumped)");
	} else {
		(void) printf("exited with status %d", WEXITSTATUS(wstat));
	}
	(void) printf("\n");
}
Пример #9
0
extern int
operand2sig (char const *operand, char *signame)
{
    int signum;

    if (ISDIGIT (*operand))
    {
        char *endp;
        long int l = (errno = 0, strtol (operand, &endp, 10));
        int i = l;
        signum = (operand == endp || *endp || errno || i != l ? -1
                  : WIFSIGNALED (i) ? WTERMSIG (i) : i);
    }
    else
    {
        /* Convert signal to upper case in the C locale, not in the
           current locale.  Don't assume ASCII; it might be EBCDIC.  */
        char *upcased = xstrdup (operand);
        char *p;
        for (p = upcased; *p; p++)
            if (strchr ("abcdefghijklmnopqrstuvwxyz", *p))
                *p += 'A' - 'a';

        /* Look for the signal name, possibly prefixed by "SIG",
           and possibly lowercased.  */
        if (!(str2sig (upcased, &signum) == 0
                || (upcased[0] == 'S' && upcased[1] == 'I' && upcased[2] == 'G'
                    && str2sig (upcased + 3, &signum) == 0)))
            signum = -1;

        free (upcased);
    }

    if (signum < 0 || sig2str (signum, signame) != 0)
    {
        error (0, 0, _("%s: invalid signal"), operand);
        return -1;
    }

    return signum;
}
Пример #10
0
/*
 * int method_run()
 *   Execute the type method of instp.  If it requires a fork(), wait for it
 *   to return and return its exit code in *exit_code.  Otherwise set
 *   *exit_code to 0 if the method succeeds & -1 if it fails.  If the
 *   repository connection is broken, it is rebound, but inst may not be
 *   reset.
 *   Returns
 *     0 - success
 *     EINVAL - A correct method or method context couldn't be retrieved.
 *     EIO - Contract kill failed.
 *     EFAULT - Method couldn't be executed successfully.
 *     ELOOP - Retry threshold exceeded.
 *     ECANCELED - inst was deleted from the repository before method was run
 *     ERANGE - Timeout retry threshold exceeded.
 *     EAGAIN - Failed due to external cause, retry.
 */
int
method_run(restarter_inst_t **instp, int type, int *exit_code)
{
	char *method;
	int ret_status;
	pid_t pid;
	method_restart_t restart_on;
	uint_t cte_mask;
	uint8_t need_session;
	scf_handle_t *h;
	scf_snapshot_t *snap;
	const char *mname;
	const char *errstr;
	struct method_context *mcp;
	int result = 0, timeout_fired = 0;
	int sig, r;
	boolean_t transient;
	uint64_t timeout;
	uint8_t timeout_retry;
	ctid_t ctid;
	int ctfd = -1;
	ct_evthdl_t ctev;
	uint_t evtype;
	restarter_inst_t *inst = *instp;
	int id = inst->ri_id;
	int forkerr;

	assert(PTHREAD_MUTEX_HELD(&inst->ri_lock));
	assert(instance_in_transition(inst));

	if (inst->ri_mi_deleted)
		return (ECANCELED);

	*exit_code = 0;

	assert(0 <= type && type <= 2);
	mname = method_names[type];

	if (type == METHOD_START)
		inst->ri_pre_online_hook();

	h = scf_instance_handle(inst->ri_m_inst);

	snap = scf_snapshot_create(h);
	if (snap == NULL ||
	    scf_instance_get_snapshot(inst->ri_m_inst, "running", snap) != 0) {
		log_framework(LOG_DEBUG,
		    "Could not get running snapshot for %s.  "
		    "Using editing version to run method %s.\n",
		    inst->ri_i.i_fmri, mname);
		scf_snapshot_destroy(snap);
		snap = NULL;
	}

	/*
	 * After this point, we may be logging to the instance log.
	 * Make sure we've noted where that log is as a property of
	 * the instance.
	 */
	r = libscf_note_method_log(inst->ri_m_inst, st->st_log_prefix,
	    inst->ri_logstem);
	if (r != 0) {
		log_framework(LOG_WARNING,
		    "%s: couldn't note log location: %s\n",
		    inst->ri_i.i_fmri, strerror(r));
	}

	if ((method = libscf_get_method(h, type, inst, snap, &restart_on,
	    &cte_mask, &need_session, &timeout, &timeout_retry)) == NULL) {
		if (errno == LIBSCF_PGROUP_ABSENT)  {
			log_framework(LOG_DEBUG,
			    "%s: instance has no method property group '%s'.\n",
			    inst->ri_i.i_fmri, mname);
			if (type == METHOD_REFRESH)
				log_instance(inst, B_TRUE, "No '%s' method "
				    "defined.  Treating as :true.", mname);
			else
				log_instance(inst, B_TRUE, "Method property "
				    "group '%s' is not present.", mname);
			scf_snapshot_destroy(snap);
			return (0);
		} else if (errno == LIBSCF_PROPERTY_ABSENT)  {
			log_framework(LOG_DEBUG,
			    "%s: instance has no '%s/exec' method property.\n",
			    inst->ri_i.i_fmri, mname);
			log_instance(inst, B_TRUE, "Method property '%s/exec "
			    "is not present.", mname);
			scf_snapshot_destroy(snap);
			return (0);
		} else {
			log_error(LOG_WARNING,
			    "%s: instance libscf_get_method failed\n",
			    inst->ri_i.i_fmri);
			scf_snapshot_destroy(snap);
			return (EINVAL);
		}
	}

	/* open service contract if stopping a non-transient service */
	if (type == METHOD_STOP && (!instance_is_transient_style(inst))) {
		if (inst->ri_i.i_primary_ctid == 0) {
			/* service is not running, nothing to stop */
			log_framework(LOG_DEBUG, "%s: instance has no primary "
			    "contract, no service to stop.\n",
			    inst->ri_i.i_fmri);
			scf_snapshot_destroy(snap);
			return (0);
		}
		if ((ctfd = contract_open(inst->ri_i.i_primary_ctid, "process",
		    "events", O_RDONLY)) < 0) {
			result = EFAULT;
			log_instance(inst, B_TRUE, "Could not open service "
			    "contract %ld.  Stop method not run.\n",
			    inst->ri_i.i_primary_ctid);
			goto out;
		}
	}

	if (restarter_is_null_method(method)) {
		log_framework(LOG_DEBUG, "%s: null method succeeds\n",
		    inst->ri_i.i_fmri);

		log_instance(inst, B_TRUE, "Executing %s method (null)", mname);

		if (type == METHOD_START)
			write_status(inst, mname, 0);
		goto out;
	}

	sig = restarter_is_kill_method(method);
	if (sig >= 0) {

		if (inst->ri_i.i_primary_ctid == 0) {
			log_error(LOG_ERR, "%s: :kill with no contract\n",
			    inst->ri_i.i_fmri);
			result = EINVAL;
			goto out;
		}

		log_framework(LOG_DEBUG,
		    "%s: :killing contract with signal %d\n",
		    inst->ri_i.i_fmri, sig);

		log_instance(inst, B_TRUE, "Executing %s method (:kill)",
		    mname);

		if (contract_kill(inst->ri_i.i_primary_ctid, sig,
		    inst->ri_i.i_fmri) != 0) {
			result = EIO;
			goto out;
		} else
			goto assured_kill;
	}

	log_framework(LOG_DEBUG, "%s: forking to run method %s\n",
	    inst->ri_i.i_fmri, method);

	errstr = restarter_get_method_context(RESTARTER_METHOD_CONTEXT_VERSION,
	    inst->ri_m_inst, snap, mname, method, &mcp);

	if (errstr != NULL) {
		log_error(LOG_WARNING, "%s: %s\n", inst->ri_i.i_fmri, errstr);
		result = EINVAL;
		goto out;
	}

	r = method_ready_contract(inst, type, restart_on, cte_mask);
	if (r != 0) {
		assert(r == ECANCELED);
		assert(inst->ri_mi_deleted);
		restarter_free_method_context(mcp);
		result = ECANCELED;
		goto out;
	}

	/*
	 * Validate safety of method contexts, to save children work.
	 */
	if (!restarter_rm_libs_loadable())
		log_framework(LOG_DEBUG, "%s: method contexts limited "
		    "to root-accessible libraries\n", inst->ri_i.i_fmri);

	/*
	 * If the service is restarting too quickly, send it to
	 * maintenance.
	 */
	if (type == METHOD_START) {
		method_record_start(inst);
		if (method_rate_critical(inst)) {
			log_instance(inst, B_TRUE, "Restarting too quickly, "
			    "changing state to maintenance");
			result = ELOOP;
			goto out;
		}
	}

	pid = startd_fork1(&forkerr);
	if (pid == 0)
		exec_method(inst, type, method, mcp, need_session);

	if (pid == -1) {
		if (forkerr == EAGAIN)
			result = EAGAIN;
		else
			result = EFAULT;

		log_error(LOG_WARNING,
		    "%s: Couldn't fork to execute method %s: %s\n",
		    inst->ri_i.i_fmri, method, strerror(forkerr));

		goto out;
	}

	restarter_free_method_context(mcp);

	/*
	 * Get the contract id, decide whether it is primary or transient, and
	 * stash it in inst & the repository.
	 */
	method_store_contract(inst, type, &ctid);

	/*
	 * Similarly for the start method PID.
	 */
	if (type == METHOD_START && !inst->ri_mi_deleted)
		(void) libscf_write_start_pid(inst->ri_m_inst, pid);

	if (instance_is_wait_style(inst) && type == METHOD_START) {
		/* Wait style instances don't get timeouts on start methods. */
		if (wait_register(pid, inst->ri_i.i_fmri, 1, 0)) {
			log_error(LOG_WARNING,
			    "%s: couldn't register %ld for wait\n",
			    inst->ri_i.i_fmri, pid);
			result = EFAULT;
			goto contract_out;
		}
		write_status(inst, mname, 0);

	} else {
		int r, err;
		time_t start_time;
		time_t end_time;

		/*
		 * Because on upgrade/live-upgrade we may have no chance
		 * to override faulty timeout values on the way to
		 * manifest import, all services on the path to manifest
		 * import are treated the same as INFINITE timeout services.
		 */

		start_time = time(NULL);
		if (timeout != METHOD_TIMEOUT_INFINITE && !is_timeout_ovr(inst))
			timeout_insert(inst, ctid, timeout);
		else
			timeout = METHOD_TIMEOUT_INFINITE;

		/* Unlock the instance while waiting for the method. */
		MUTEX_UNLOCK(&inst->ri_lock);

		do
			r = waitpid(pid, &ret_status, NULL);
		while (r == -1 && errno == EINTR);
		if (r == -1)
			err = errno;

		/* Re-grab the lock. */
		inst = inst_lookup_by_id(id);

		/*
		 * inst can't be removed, as the removal thread waits
		 * for completion of this one.
		 */
		assert(inst != NULL);
		*instp = inst;

		if (inst->ri_timeout != NULL && inst->ri_timeout->te_fired)
			timeout_fired = 1;

		timeout_remove(inst, ctid);

		log_framework(LOG_DEBUG,
		    "%s method for %s exited with status %d.\n", mname,
		    inst->ri_i.i_fmri, WEXITSTATUS(ret_status));

		if (r == -1) {
			log_error(LOG_WARNING,
			    "Couldn't waitpid() for %s method of %s (%s).\n",
			    mname, inst->ri_i.i_fmri, strerror(err));
			result = EFAULT;
			goto contract_out;
		}

		if (type == METHOD_START)
			write_status(inst, mname, ret_status);

		/* return ERANGE if this service doesn't retry on timeout */
		if (timeout_fired == 1 && timeout_retry == 0) {
			result = ERANGE;
			goto contract_out;
		}

		if (!WIFEXITED(ret_status)) {
			/*
			 * If method didn't exit itself (it was killed by an
			 * external entity, etc.), consider the entire
			 * method_run as failed.
			 */
			if (WIFSIGNALED(ret_status)) {
				char buf[SIG2STR_MAX];
				(void) sig2str(WTERMSIG(ret_status), buf);

				log_error(LOG_WARNING, "%s: Method \"%s\" "
				    "failed due to signal %s.\n",
				    inst->ri_i.i_fmri, method, buf);
				log_instance(inst, B_TRUE, "Method \"%s\" "
				    "failed due to signal %s", mname, buf);
			} else {
				log_error(LOG_WARNING, "%s: Method \"%s\" "
				    "failed with exit status %d.\n",
				    inst->ri_i.i_fmri, method,
				    WEXITSTATUS(ret_status));
				log_instance(inst, B_TRUE, "Method \"%s\" "
				    "failed with exit status %d", mname,
				    WEXITSTATUS(ret_status));
			}
			result = EAGAIN;
			goto contract_out;
		}

		*exit_code = WEXITSTATUS(ret_status);
		if (*exit_code != 0) {
			log_error(LOG_WARNING,
			    "%s: Method \"%s\" failed with exit status %d.\n",
			    inst->ri_i.i_fmri, method, WEXITSTATUS(ret_status));
		}

		log_instance(inst, B_TRUE, "Method \"%s\" exited with status "
		    "%d", mname, *exit_code);

		if (*exit_code != 0)
			goto contract_out;

		end_time = time(NULL);

		/* Give service contract remaining seconds to empty */
		if (timeout != METHOD_TIMEOUT_INFINITE)
			timeout -= (end_time - start_time);
	}

assured_kill:
	/*
	 * For stop methods, assure that the service contract has emptied
	 * before returning.
	 */
	if (type == METHOD_STOP && (!instance_is_transient_style(inst)) &&
	    !(contract_is_empty(inst->ri_i.i_primary_ctid))) {

		if (timeout != METHOD_TIMEOUT_INFINITE)
			timeout_insert(inst, inst->ri_i.i_primary_ctid,
			    timeout);

		for (;;) {
			do {
				r = ct_event_read_critical(ctfd, &ctev);
			} while (r == EINTR);
			if (r != 0)
				break;

			evtype = ct_event_get_type(ctev);
			ct_event_free(ctev);
			if (evtype == CT_PR_EV_EMPTY)
				break;
		}
		if (r) {
			result = EFAULT;
			log_instance(inst, B_TRUE, "Error reading service "
			    "contract %ld.\n", inst->ri_i.i_primary_ctid);
		}

		if (timeout != METHOD_TIMEOUT_INFINITE)
			if (inst->ri_timeout->te_fired)
				result = EFAULT;

		timeout_remove(inst, inst->ri_i.i_primary_ctid);
	}

contract_out:
	/* Abandon contracts for transient methods & methods that fail. */
	transient = method_is_transient(inst, type);
	if ((transient || *exit_code != 0 || result != 0) &&
	    (restarter_is_kill_method(method) < 0))
		method_remove_contract(inst, !transient, B_TRUE);

out:
	if (ctfd >= 0)
		(void) close(ctfd);
	scf_snapshot_destroy(snap);
	free(method);
	return (result);
}
Пример #11
0
/*ARGSUSED*/
static int
d_siginfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	static const char *const msname[] = {
		"USER", "SYSTEM", "TRAP", "TFAULT", "DFAULT", "KFAULT",
		"USER_LOCK", "SLEEP", "WAIT_CPU", "STOPPED"
	};

	char signame[SIG2STR_MAX];
	siginfo_t si;
	int i;

	if (argc != 0)
		return (DCMD_USAGE);

	if (mdb_vread(&si, sizeof (si), addr) != sizeof (si)) {
		mdb_warn("failed to read siginfo at %p", addr);
		return (DCMD_ERR);
	}

	if (sig2str(si.si_signo, signame) == -1)
		(void) strcpy(signame, "unknown");

	mdb_printf("  signal %5d (%s)\n", si.si_signo, signame);
	mdb_printf("  code   %5d (", si.si_code);

	switch (si.si_code) {
	case SI_NOINFO:
		mdb_printf("no info");
		break;
	case SI_DTRACE:
		mdb_printf("from DTrace raise() action");
		break;
	case SI_RCTL:
		mdb_printf("from rctl action");
		break;
	case SI_USER:
		mdb_printf("user generated via kill");
		break;
	case SI_LWP:
		mdb_printf("user generated via lwp_kill");
		break;
	case SI_QUEUE:
		mdb_printf("user generated via sigqueue");
		break;
	case SI_TIMER:
		mdb_printf("from timer expiration");
		break;
	case SI_ASYNCIO:
		mdb_printf("from async i/o completion");
		break;
	case SI_MESGQ:
		mdb_printf("from message arrival");
		break;
	default:
		if (SI_FROMUSER(&si))
			mdb_printf("from user process");
		else
			mdb_printf("from kernel");
	}

	mdb_printf(")\n  errno  %5d (%s)\n",
	    si.si_errno, strerror(si.si_errno));

	if (si.si_code == SI_USER || si.si_code == SI_QUEUE) {
		mdb_printf("  signal sent from PID %d (uid %d)\n",
		    si.si_pid, si.si_uid);
	}

	if (si.si_code == SI_QUEUE) {
		mdb_printf("  signal value = 0t%d / %p\n",
		    si.si_value.sival_int, si.si_value.sival_ptr);
	}

	switch (si.si_signo) {
	case SIGCLD:
		mdb_printf("  signal sent from child PID %d (uid %d)\n",
		    si.si_pid, si.si_uid);
		mdb_printf("  usr time = 0t%ld ticks, sys time = 0t%ld ticks\n",
		    si.si_utime, si.si_stime);
		mdb_printf("  wait status = 0x%x\n", si.si_status);
		break;

	case SIGSEGV:
	case SIGBUS:
	case SIGILL:
	case SIGTRAP:
	case SIGFPE:
		mdb_printf("  fault address = 0x%p\n  trapno = %d\n",
		    si.si_addr, si.si_trapno);
		mdb_printf("  instruction address = 0x%p %lA\n",
		    si.si_pc, si.si_pc);
		break;

	case SIGPOLL:
	case SIGXFSZ:
		mdb_printf("  fd = %d  band = 0x%lx\n",
		    si.si_fd, si.si_band);
		break;

	case SIGPROF:
		mdb_printf("  last fault address = 0x%p fault type = %d\n",
		    si.si_faddr, si.si_fault);
		mdb_printf("  timestamp = 0t%ld sec 0t%ld nsec\n",
		    si.si_tstamp.tv_sec, si.si_tstamp.tv_nsec);

		if (si.__data.__prof.__syscall != 0) {
			mdb_printf("  system call %d (", si.si_syscall);
			if (si.si_nsysarg > 0) {
				mdb_printf("%lx", si.si_sysarg[0]);
				for (i = 1; i < si.si_nsysarg; i++)
					mdb_printf(", %lx", si.si_sysarg[i]);
			}
			mdb_printf("  )\n");
		}

		for (i = 0; i < sizeof (msname) / sizeof (msname[0]); i++) {
			mdb_printf("  mstate[\"%s\"] = %d\n",
			    msname[i], si.si_mstate[i]);
		}
		break;
	}

	return (DCMD_OK);
}
Пример #12
0
int
main(int argc, char **argv)
{
	dsvcd_datastore_t	**ds_table;
	dsvc_datastore_t	dd;
	dsvc_synchtype_t	synchtype;
	char			**modules;
	unsigned int		i, j;
	int			debug_level = 0;
	boolean_t		is_daemon = B_TRUE;
	boolean_t		is_verbose = B_FALSE;
	int			sig, nmodules, nsynchmods, c;
	sigset_t		sigset;
	char			signame[SIG2STR_MAX];
	char			*progname;
	void			*stackbase;
	unsigned int		stacksize = 16 * 1024;
	struct rlimit		rl;

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	/*
	 * Mask all signals except SIGABRT; doing this here ensures that
	 * all threads created through door_create() have them masked too.
	 */
	(void) sigfillset(&sigset);
	(void) sigdelset(&sigset, SIGABRT);
	(void) thr_sigsetmask(SIG_BLOCK, &sigset, NULL);

	/*
	 * Figure out our program name; just keep the final piece so that
	 * our dhcpmsg() messages don't get too long.
	 */
	progname = strrchr(argv[0], '/');
	if (progname != NULL)
		progname++;
	else
		progname = argv[0];

	/*
	 * Set the door thread creation procedure so that all of our
	 * threads are created with thread stacks with backing store.
	 */
	(void) door_server_create(doorserv_create);

	while ((c = getopt(argc, argv, "d:fv")) != EOF) {
		switch (c) {

		case 'd':
			debug_level = atoi(optarg);
			break;

		case 'f':
			is_daemon = B_FALSE;
			break;

		case 'v':
			is_verbose = B_TRUE;
			break;

		case '?':
			(void) fprintf(stderr,
			    gettext("usage: %s [-dn] [-f] [-v]\n"), progname);
			return (EXIT_FAILURE);

		default:
			break;
		}
	}

	if (geteuid() != 0) {
		dhcpmsg_init(progname, B_FALSE, is_verbose, debug_level);
		dhcpmsg(MSG_ERROR, "must be super-user");
		dhcpmsg_fini();
		return (EXIT_FAILURE);
	}

	if (is_daemon && daemonize() == 0) {
		dhcpmsg_init(progname, B_FALSE, is_verbose, debug_level);
		dhcpmsg(MSG_ERROR, "cannot become daemon, exiting");
		dhcpmsg_fini();
		return (EXIT_FAILURE);
	}

	dhcpmsg_init(progname, is_daemon, is_verbose, debug_level);
	(void) atexit(dhcpmsg_fini);

	/*
	 * Max out the number available descriptors since we need to
	 * allocate two per held lock.
	 */
	rl.rlim_cur = RLIM_INFINITY;
	rl.rlim_max = RLIM_INFINITY;
	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
		dhcpmsg(MSG_ERR, "setrlimit failed");

	(void) enable_extended_FILE_stdio(-1, -1);

	if (enumerate_dd(&modules, &nmodules) != DSVC_SUCCESS) {
		dhcpmsg(MSG_ERROR, "cannot enumerate public modules, exiting");
		return (EXIT_FAILURE);
	}

	/*
	 * NOTE: this code assumes that a module that needs dsvclockd will
	 * always need it (even as the container version is ramped).  If
	 * this becomes bogus in a future release, we'll have to make this
	 * logic more sophisticated.
	 */
	nsynchmods = nmodules;
	for (i = 0; i < nmodules; i++) {
		dd.d_resource = modules[i];
		dd.d_conver = DSVC_CUR_CONVER;
		dd.d_location = "";
		if (module_synchtype(&dd, &synchtype) != DSVC_SUCCESS) {
			dhcpmsg(MSG_WARNING, "cannot determine synchronization "
			    "type for `%s', skipping", modules[i]);
			free(modules[i]);
			modules[i] = NULL;
			nsynchmods--;
			continue;
		}
		if ((synchtype & DSVC_SYNCH_STRATMASK) != DSVC_SYNCH_DSVCD) {
			free(modules[i]);
			modules[i] = NULL;
			nsynchmods--;
		}
	}

	if (nsynchmods == 0) {
		dhcpmsg(MSG_INFO, "no public modules need synchronization");
		return (EXIT_SUCCESS);
	}

	/*
	 * Allocate the datastore table; include one extra entry so that
	 * the table is NULL-terminated.
	 */
	ds_table = calloc(nsynchmods + 1, sizeof (dsvcd_datastore_t *));
	if (ds_table == NULL) {
		dhcpmsg(MSG_ERR, "cannot allocate datastore table, exiting");
		return (EXIT_FAILURE);
	}
	ds_table[nsynchmods] = NULL;

	/*
	 * Create the datastores (which implicitly creates the doors).
	 * then sit around and wait for requests to come in on the doors.
	 */
	for (i = 0, j = 0; i < nmodules; i++) {
		if (modules[i] != NULL) {
			ds_table[j] = ds_create(modules[i], svc_lock);
			if (ds_table[j] == NULL) {
				while (j-- > 0)
					ds_destroy(ds_table[j]);
				return (EXIT_FAILURE);
			}
			free(modules[i]);
			j++;
		}
	}
	free(modules);

	stackbase = stack_create(&stacksize);
	if (stackbase == NULL)
		dhcpmsg(MSG_ERR, "cannot create reaper stack; containers "
		    "will not be reaped");
	else {
		errno = thr_create(stackbase, stacksize, reaper, ds_table,
		    THR_DAEMON, NULL);
		if (errno != 0) {
			dhcpmsg(MSG_ERR, "cannot create reaper thread; "
			    "containers will not be reaped");
			stack_destroy(stackbase, stacksize);
		}
	}

	/*
	 * Synchronously wait for a QUIT, TERM, or INT, then shutdown.
	 */
	(void) sigemptyset(&sigset);
	(void) sigaddset(&sigset, SIGQUIT);
	(void) sigaddset(&sigset, SIGTERM);
	(void) sigaddset(&sigset, SIGINT);

	(void) sigwait(&sigset, &sig);
	if (sig != SIGTERM && sig != SIGQUIT && sig != SIGINT)
		dhcpmsg(MSG_WARNING, "received unexpected signal");

	if (sig2str(sig, signame) == -1)
		(void) strlcpy(signame, "???", sizeof (signame));

	dhcpmsg(MSG_INFO, "shutting down via SIG%s", signame);

	for (i = 0; i < nsynchmods; i++)
		ds_destroy(ds_table[i]);

	return (EXIT_SUCCESS);
}
Пример #13
0
int main (int argc, char **argv)
{
	int c;
	int sig;
	int s_flag;
	int l_flag;
	int err_flag;
	char buf [SIG2STR_MAX];
	pid_t pid;

	s_flag= 0;
	l_flag =0;
	err_flag = 0;
	opterr = 0;

	while ((c = getopt (argc, argv, "ls:")) != EOF) {
		switch (c) {
			case 'l':
				if (s_flag)	
					err_flag++;

				l_flag++;
				break;

			case 's':
				if ((l_flag) || (s_flag))
					err_flag++;

				s_flag++;
				snprintf (buf, SIG2STR_MAX - 1, "%s", optarg);
				break;

			default:
				err_flag++;
				break;
		}
	}

	if ((!l_flag) && (!s_flag))
		err_flag++;

	if (((s_flag) && (optind == argc)) || ((l_flag) && (optind != argc)))
		err_flag++;

	if (err_flag) {
		log_msg ("Usage: ssp_kill -l");
		log_msg ("       ssp_kill -s signal PID");
		exit (1);
	}

	if (l_flag) {
		for (sig = 0; sig <= MAXSIG; sig++) {
			sig2str (sig, buf);
			printf ("%s ", buf);
		}
		printf ("\n");
	}
	else {
		if (str2sig (buf, &sig) == -1)
			err_quit ("ssp_kill: %s: No such signal", buf);
		for (; optind < argc; optind++) {
			pid = atoi (argv [optind]);
			if (kill (pid, sig) == -1)
				err_ret ("Can't kill PID %d", pid);
		}
	}

	return (0);
}
Пример #14
0
/*ARGSUSED*/
static void
flt_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
{
	static const struct rlimit rl = {
		(rlim_t)RLIM_INFINITY, (rlim_t)RLIM_INFINITY
	};

	const mdb_idcmd_t *idcp = NULL;

	if (mdb.m_frame != NULL && mdb.m_frame->f_cp != NULL)
		idcp = mdb.m_frame->f_cp->c_dcmd;

	if (sip != NULL)
		bcopy(sip, &_mdb_abort_info, sizeof (_mdb_abort_info));
	if (ucp != NULL)
		bcopy(ucp, &_mdb_abort_ctx, sizeof (_mdb_abort_ctx));

	_mdb_abort_info.si_signo = sig;
	(void) mdb_signal_sethandler(sig, SIG_DFL, NULL);

	/*
	 * If there is no current dcmd, or the current dcmd comes from a
	 * builtin module, we don't allow resume and always core dump.
	 */
	if (idcp == NULL || idcp->idc_modp == NULL ||
	    idcp->idc_modp == &mdb.m_rmod || idcp->idc_modp->mod_hdl == NULL)
		goto dump;

	if (mdb.m_term != NULL) {
		struct frame *fr = (struct frame *)
		    (ucp->uc_mcontext.gregs[STACK_REGISTER] + STACK_BIAS);

		char signame[SIG2STR_MAX];
		int i = 1;
		char c;

		if (sig2str(sig, signame) == -1) {
			mdb_iob_printf(mdb.m_err,
			    "\n*** %s: received signal %d at:\n",
			    mdb.m_pname, sig);
		} else {
			mdb_iob_printf(mdb.m_err,
			    "\n*** %s: received signal %s at:\n",
			    mdb.m_pname, signame);
		}

		if (ucp->uc_mcontext.gregs[REG_PC] != 0)
			print_frame(ucp->uc_mcontext.gregs[REG_PC], i++);

		while (fr != NULL && valid_frame(fr) && fr->fr_savpc != 0) {
			print_frame(fr->fr_savpc, i++);
			fr = (struct frame *)
			    ((uintptr_t)fr->fr_savfp + STACK_BIAS);
		}

query:
		mdb_iob_printf(mdb.m_err, "\n%s: (c)ore dump, (q)uit, "
		    "(r)ecover, or (s)top for debugger [cqrs]? ", mdb.m_pname);

		mdb_iob_flush(mdb.m_err);

		for (;;) {
			if (IOP_READ(mdb.m_term, &c, sizeof (c)) != sizeof (c))
				goto dump;

			switch (c) {
			case 'c':
			case 'C':
				(void) setrlimit(RLIMIT_CORE, &rl);
				mdb_iob_printf(mdb.m_err, "\n%s: attempting "
				    "to dump core ...\n", mdb.m_pname);
				goto dump;

			case 'q':
			case 'Q':
				mdb_iob_discard(mdb.m_out);
				mdb_iob_nl(mdb.m_err);
				(void) mdb_signal_unblockall();
				terminate(1);
				/*NOTREACHED*/

			case 'r':
			case 'R':
				mdb_iob_printf(mdb.m_err, "\n%s: unloading "
				    "module '%s' ...\n", mdb.m_pname,
				    idcp->idc_modp->mod_name);

				(void) mdb_module_unload(
				    idcp->idc_modp->mod_name, 0);

				(void) mdb_signal_sethandler(sig,
				    flt_handler, NULL);

				_mdb_abort_rcount++;
				mdb.m_intr = 0;
				mdb.m_pend = 0;

				(void) mdb_signal_unblockall();
				longjmp(mdb.m_frame->f_pcb, MDB_ERR_ABORT);
				/*NOTREACHED*/

			case 's':
			case 'S':
				mdb_iob_printf(mdb.m_err, "\n%s: "
				    "attempting to stop pid %d ...\n",
				    mdb.m_pname, (int)getpid());

				/*
				 * Stop ourself; if this fails or we are
				 * subsequently continued, ask again.
				 */
				(void) mdb_signal_raise(SIGSTOP);
				(void) mdb_signal_unblockall();
				goto query;
			}
		}
	}

dump:
	if (SI_FROMUSER(sip)) {
		(void) mdb_signal_block(sig);
		(void) mdb_signal_raise(sig);
	}

	(void) sigfillset(&ucp->uc_sigmask);
	(void) sigdelset(&ucp->uc_sigmask, sig);

	if (_mdb_abort_str == NULL)
		_mdb_abort_str = "fatal signal received";

	ucp->uc_flags |= UC_SIGMASK;
	(void) setcontext(ucp);
}
Пример #15
0
static void
read_signal_input(void)
{
    uint8_t signal;

    /* This read is atomic since sizeof(int) < PIPE_BUF!
     * It also doesn't block since all data is already
     * available (otherwise select wouldn't tell us there
     * was data).
     */
    if (read(signal_pipe[0], &signal, sizeof(uint8_t)) < 0) {
        warn(_("Cannot read from signal pipe - %s\n"), errstr);
        running = false;
        return;
    }

    if (signal == SIGTERM) {
        warn(_("Received TERM signal, shutting down.\n"));
        running = false;
    }
    else if (signal == SIGINT) {
        screen_erase_and_new_line();
    }
    else if (signal == SIGCHLD) {
        pid_t child;
        int status;

        while ((child = waitpid(-1, &status, WNOHANG)) > 0) {
            char *name;

            if (child == shell_child) {
                screen_wakeup(WIFSIGNALED(status) && WTERMSIG(status) == SIGINT);
                shell_child = -1;
                name = _("Shell process");
            } else if (child == lookup_child) {
                name = _("Lookup process");
                running = false;
            } else if (child == parse_child) {
                name = _("Parse process");
                running = false;
            } else if (child == update_child) {
                name = _("FileList Update process");
                running = false;
            } else {
                /* Assume it was a child process */
                name = _("User process");
            }
            if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
                warn(_("%s exited with return code %d.\n"), name, WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)) {
                char signame[SIG2STR_MAX];

                if (sig2str(WTERMSIG(status), signame) < 0)
                    sprintf(signame, "%d", WTERMSIG(status));
                warn(_("%s terminated by signal %s.\n"), name, signame);
            }
        }
        if (child < 0 && errno != ECHILD)
            warn(_("Cannot wait for processes - %s\n"), errstr);
    }
    else if (signal == SIGUSR1) {
        /* Not implemented yet, do nothing for now. */
    }
}
Пример #16
0
/*ARGSUSED*/
static void *
handle_sig(void *arg)
{
	pool_conf_t *conf = NULL;
	pool_elem_t *pe;
	pool_value_t *val;
	const char *err_desc;
	int keep_handling = 1;

	while (keep_handling) {
		int sig;
		char buf[SIG2STR_MAX];

		if ((sig = sigwait(&hdl_set)) < 0) {
			/*
			 * We used forkall() previously to ensure that
			 * all threads started by the JVM are
			 * duplicated in the child. Since forkall()
			 * can cause blocking system calls to be
			 * interrupted, check to see if the errno is
			 * EINTR and if it is wait again.
			 */
			if (errno == EINTR)
				continue;
			(void) pthread_mutex_lock(&jvm_lock);
			pu_terminate("unexpected error: %d\n", errno);
			keep_handling = 0;
		} else
			(void) pthread_mutex_lock(&jvm_lock);
		(void) sig2str(sig, buf);
		switch (sig) {
		case SIGHUP:
			if ((conf = pool_conf_alloc()) == NULL) {
				err_desc = pool_strerror(pool_error());
				goto destroy;
			}
			if (pool_conf_open(conf, pool_dynamic_location(),
			    PO_RDWR) != 0) {
				err_desc = pool_strerror(pool_error());
				goto destroy;
			}

			if ((val = pool_value_alloc()) == NULL) {
				err_desc = pool_strerror(pool_error());
				goto destroy;
			}
			pe = pool_conf_to_elem(conf);
			pool_value_set_bool(val, 1);
			if (pool_put_property(conf, pe, "system.poold.sighup",
			    val) != PO_SUCCESS) {
				err_desc = pool_strerror(pool_error());
				pool_value_free(val);
				goto destroy;
			}
			pool_value_free(val);
			(void) pool_rm_property(conf, pe,
			    "system.poold.sighup");
			if (pool_conf_commit(conf, 0) != PO_SUCCESS) {
				err_desc = pool_strerror(pool_error());
				goto destroy;
			}
			(void) pool_conf_close(conf);
			pool_conf_free(conf);
			break;
destroy:
			if (conf) {
				(void) pool_conf_close(conf);
				pool_conf_free(conf);
			}
			pu_terminate(err_desc);
			keep_handling = 0;
			break;
		case SIGINT:
		case SIGTERM:
		default:
			pu_terminate("terminating due to signal: SIG%s\n", buf);
			keep_handling = 0;
			break;
		}
		(void) pthread_mutex_unlock(&jvm_lock);
	}
	pthread_exit(NULL);
	/*NOTREACHED*/
	return (NULL);
}
Пример #17
0
void
event_process(FILE *file, ct_evthdl_t ev, int verbose)
{
	uint_t type;
	pid_t pid;
	char *s;

	type = ct_event_get_type(ev);
	if (ct_pr_event_get_pid(ev, &pid) != 0) {
		(void) fprintf(file, dgettext(TEXT_DOMAIN, "[bad event]\n"));
		return;
	}

	switch (type) {
	case CT_PR_EV_EMPTY:
		s = dgettext(TEXT_DOMAIN, "contract empty\n");
		break;
	case CT_PR_EV_FORK:
		s = dgettext(TEXT_DOMAIN, "process %d was created\n");
		break;
	case CT_PR_EV_EXIT:
		s = dgettext(TEXT_DOMAIN, "process %d exited\n");
		break;
	case CT_PR_EV_CORE:
		s = dgettext(TEXT_DOMAIN, "process %d dumped core\n");
		break;
	case CT_PR_EV_SIGNAL:
		s = dgettext(TEXT_DOMAIN,
		    "process %d received a fatal signal\n");
		break;
	case CT_PR_EV_HWERR:
		s = dgettext(TEXT_DOMAIN,
		    "process %d was killed by a hardware error\n");
		break;
	default:
		s = dgettext(TEXT_DOMAIN, "process %d sent an unknown event\n");
		break;
	}

	/*LINTED*/
	(void) fprintf(file, s, pid);
	if (!verbose)
		return;

	switch (type) {
		int i;
		const char *c;
		char buf[SIG2STR_MAX];
		ctid_t ctid;
	case CT_PR_EV_FORK:
		if (ct_pr_event_get_ppid(ev, &pid) == 0)
			(void) fprintf(file, dgettext(TEXT_DOMAIN,
			    "\tparent pid: %d\n"), pid);
		break;
	case CT_PR_EV_EXIT:
		if (ct_pr_event_get_exitstatus(ev, &i) != 0)
			break;
		(void) fprintf(file,
		    dgettext(TEXT_DOMAIN, "\twait status: 0x%x"), i);
		if (WIFEXITED(i)) {
			(void) fprintf(file, dgettext(TEXT_DOMAIN,
			    " (exited, code %d)\n"), WEXITSTATUS(i));
		} else if (WIFSIGNALED(i)) {
			int sig = WTERMSIG(i);
			(void) fprintf(file,
			    dgettext(TEXT_DOMAIN, " (signal %d"), sig);
			if (sig2str(sig, buf) == 0)
				(void) fprintf(file,
				    dgettext(TEXT_DOMAIN, " (SIG%s)"), buf);
			if (WCOREDUMP(i))
				(void) fprintf(file,
				    dgettext(TEXT_DOMAIN, ", core dumped)\n"));
			else
				(void) fprintf(file,
				    dgettext(TEXT_DOMAIN, ")\n"));
		} else {
			/*
			 * We really shouldn't get here.
			 */
			(void) fprintf(file, dgettext(TEXT_DOMAIN, "\n"));
		}
		break;
	case CT_PR_EV_CORE:
		if (ct_pr_event_get_pcorefile(ev, &c) == 0)
			(void) fprintf(file, dgettext(TEXT_DOMAIN,
			    "\tprocess core: %s\n"), c);
		if (ct_pr_event_get_gcorefile(ev, &c) == 0)
			(void) fprintf(file, dgettext(TEXT_DOMAIN,
			    "\tglobal core: %s\n"), c);
		if (ct_pr_event_get_zcorefile(ev, &c) == 0)
			(void) fprintf(file, dgettext(TEXT_DOMAIN,
			    "\tglobal zone core: %s\n"), c);
		break;
	case CT_PR_EV_SIGNAL:
		if (ct_pr_event_get_signal(ev, &i) == 0) {
			if (sig2str(i, buf) == -1)
				(void) fprintf(file, dgettext(TEXT_DOMAIN,
				    "\tsignal: %d\n"), i);
			else
				(void) fprintf(file, dgettext(TEXT_DOMAIN,
				    "\tsignal: %d (SIG%s)\n"), i, buf);
		}
		if (ct_pr_event_get_sender(ev, &pid) == 0)
			(void) fprintf(file, dgettext(TEXT_DOMAIN,
			    "\tsender pid: %d\n"), pid);
		if (ct_pr_event_get_senderct(ev, &ctid) == 0)
			(void) fprintf(file, dgettext(TEXT_DOMAIN,
			    "\tsender ctid: %d\n"), ctid);
		break;
	}
}