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; }
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; }
/* -------------------------------------------------------------------- * 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; }