Exemplo n.º 1
0
// generic signal handler
static void signal_handler(int signo)
{
#define err signo
	if (SIGALRM == signo) {
		kill_helper();
		bb_error_msg_and_die("timed out");
	}

	// SIGCHLD. reap zombies
	if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) {
		if (WIFSIGNALED(err))
			bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err));
		if (WIFEXITED(err)) {
			G.helper_pid = 0;
			if (WEXITSTATUS(err))
				bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err));
		}
	}
#undef err
}
Exemplo n.º 2
0
/*
 * This function is called when there is socketpair input from a helper.
 * This is the answer from the helper.
 * We read the request from the socketpair, and find the associated continuation,
 * and dispatch to that continuation.
 *
 * This function should process only a single answer, and then go back
 * to the select call to get called again. This is not most efficient,
 * but is is most fair.
 *
 */
static void handle_helper_answer(struct pluto_crypto_worker *w)
{
	struct pluto_crypto_req rr;
	ssize_t actlen;
	struct pluto_crypto_req_cont *cn;

	DBG(DBG_CONTROL,
	    DBG_log("crypto helper %d has finished work (pcw_work now %d)",
		    w->pcw_helpernum,
		    w->pcw_work));

	/* read from the socketpair in one gulp */

	errno = 0;
	actlen = read(w->pcw_master_fd, (void *)&rr, sizeof(rr));

	if (actlen != sizeof(rr)) {
		if (actlen == -1) {
			loglog(RC_LOG_SERIOUS,
			       "read from crypto helper %d failed: %s.  Killing helper.",
			       w->pcw_helpernum, strerror(errno));
			kill_helper(w);
		} else if (actlen == 0) {
			/* EOF: mark worker as dead. */
			w->pcw_dead = TRUE;
		} else if (errno == 0) {
			loglog(RC_LOG_SERIOUS,
			       "read from crypto helper %d failed with short length %zd of %zu.  Killing helper.",
			       w->pcw_helpernum, actlen, sizeof(rr));
			kill_helper(w);
		} else {
			loglog(RC_LOG_SERIOUS,
			       "read from crypto helper %d failed with short length %zd of %zu (errno=%s).  Killing helper.",
			       w->pcw_helpernum, actlen, sizeof(rr), strerror(errno));
			kill_helper(w);
		}
		return;
	}

	if (rr.pcr_len != sizeof(rr)) {
		loglog(RC_LOG_SERIOUS,
		       "crypto helper %d screwed up length: %zu != %zu; killing it",
		       w->pcw_helpernum,
		       rr.pcr_len, sizeof(rr));
		kill_helper(w);
		return;
	}

	DBG(DBG_CONTROL,
		DBG_log("crypto helper %d replies to request ID %u",
			w->pcw_helpernum, rr.pcr_id));

	/* worker w can accept more work now that we have read from its socketpair */
	w->pcw_work--;

	/*
	 * if there is work queued, then send it off after reading, since this
	 * avoids the most deadlocks
	 */
	crypto_send_backlog(w);

	/* now match up request to continuation, and invoke it */
	for (cn = w->pcw_active.tqh_first;
	     cn != NULL && rr.pcr_id != cn->pcrc_id;
	     cn = cn->pcrc_list.tqe_next)
		;

	if (cn == NULL) {
		loglog(RC_LOG_SERIOUS,
		       "failed to find crypto continuation associated with request ID %u performed by crypto helper %d",
		       rr.pcr_id,
		       w->pcw_helpernum);
		return;
	}

	/* unlink it */
	TAILQ_REMOVE(&w->pcw_active, cn, pcrc_list);

	passert(cn->pcrc_func != NULL);

	DBG(DBG_CONTROL,
		DBG_log("calling continuation function %p",
			cn->pcrc_func));

	reply_stream = cn->pcrc_reply_stream;
	if (pbs_offset(&reply_stream) != 0) {
		memcpy(reply_stream.start, cn->pcrc_reply_buffer,
		       pbs_offset(&reply_stream));
		pfree(cn->pcrc_reply_buffer);
	}
	cn->pcrc_reply_buffer = NULL;

	/* call the continuation (skip if suppressed) */
	cn->pcrc_pcr = &rr;
	reset_cur_state();
	if (cn->pcrc_serialno != SOS_NOBODY)
		(*cn->pcrc_func)(cn, &rr);

	/* now free up the continuation */
	pfree(cn);
}