예제 #1
0
파일: work_thread.c 프로젝트: ntpsec/ntpsec
blocking_pipe_header *
receive_blocking_resp_internal(
	blocking_child *	c
	)
{
	blocking_pipe_header *	removed;
#ifdef USE_WORK_PIPE
	int			rc;
	char			scratch[32];

	do {
		rc = read(c->resp_read_pipe, scratch, sizeof(scratch));
	} while (-1 == rc && EINTR == errno);
#endif
	removed = c->responses[c->next_workresp];
	if (NULL != removed) {
		c->responses[c->next_workresp] = NULL;
		c->next_workresp = (1 + c->next_workresp) %
				   c->responses_alloc;
		DEBUG_ENSURE(CHILD_GONE_RESP == removed ||
			     BLOCKING_RESP_MAGIC == removed->magic_sig);
	}
	if (CHILD_GONE_RESP == removed) {
		cleanup_after_child(c);
		removed = NULL;
	}

	return removed;
}
예제 #2
0
파일: work_fork.c 프로젝트: credil/ntp
blocking_pipe_header *
receive_blocking_resp_internal(
	blocking_child *	c
	)
{
	blocking_pipe_header	hdr;
	blocking_pipe_header *	resp;
	int			rc;
	long			octets;

	DEBUG_REQUIRE(c->resp_read_pipe != -1);

	resp = NULL;
	rc = read(c->resp_read_pipe, &hdr, sizeof(hdr));

	if (rc < 0) {
		TRACE(1, ("receive_blocking_resp_internal: pipe read %m\n"));
	} else if (0 == rc) {
		/* this is the normal child exited indication */
	} else if (rc != sizeof(hdr)) {
		TRACE(1, ("receive_blocking_resp_internal: short header read %d of %lu\n",
			  rc, (u_long)sizeof(hdr)));
	} else if (BLOCKING_RESP_MAGIC != hdr.magic_sig) {
		TRACE(1, ("receive_blocking_resp_internal: header mismatch (0x%x)\n",
			  hdr.magic_sig));
	} else {
		INSIST(sizeof(hdr) < hdr.octets &&
		       hdr.octets < 16 * 1024);
		resp = emalloc(hdr.octets);
		memcpy(resp, &hdr, sizeof(*resp));
		octets = hdr.octets - sizeof(hdr);
		rc = read(c->resp_read_pipe,
			  (char *)resp + sizeof(*resp),
			  octets);

		if (rc < 0)
			TRACE(1, ("receive_blocking_resp_internal: pipe data read %m\n"));
		else if (rc < octets)
			TRACE(1, ("receive_blocking_resp_internal: short read %d of %ld\n",
				  rc, octets));
		else
			return resp;
	}

	cleanup_after_child(c);

	if (resp != NULL)
		free(resp);

	return NULL;
}
예제 #3
0
/* --------------------------------------------------------------------
 * Fetch the next response from the return queue. In case of signalling
 * via pipe, make sure the pipe is flushed, too.
 */
blocking_pipe_header *
receive_blocking_resp_internal(
	blocking_child *	c
	)
{
	blocking_pipe_header *	removed;
	size_t			qhead, qtail, slot;

#ifdef WORK_PIPE
	int			rc;
	char			scratch[32];

	do
		rc = read(c->resp_read_pipe, scratch, sizeof(scratch));
	while (-1 == rc && EINTR == errno);
#endif

	/* >>>> ACCESS LOCKING STARTS >>>> */
	wait_for_sem(c->accesslock, NULL);
	qhead = c->head_response;
	qtail = c->tail_response;
	for (removed = NULL; !removed && (qhead != qtail); ++qtail) {
		slot = qtail % c->responses_alloc;
		removed = c->responses[slot];
		c->responses[slot] = NULL;
	}
	c->tail_response = qtail;
	tickle_sem(c->accesslock);
	/* <<<< ACCESS LOCKING ENDS <<<< */

	if (NULL != removed) {
		DEBUG_ENSURE(CHILD_GONE_RESP == removed ||
			     BLOCKING_RESP_MAGIC == removed->magic_sig);
	}
	if (CHILD_GONE_RESP == removed) {
		cleanup_after_child(c);
		removed = NULL;
	}

	return removed;
}