Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polling wakeup: recover from possible faults or return error #29

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion include/arch/unix/apr_arch_poll_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ struct apr_pollcb_provider_t {
apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
apr_file_t **wakeup_pipe);
apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe);
void apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe);
apr_status_t apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe);
apr_status_t apr_pollset_wakeup_pipe_regenerate(apr_pollset_t *pollset);
apr_status_t apr_pollcb_wakeup_pipe_regenerate(apr_pollcb_t *pollcb);

#endif /* APR_ARCH_POLL_PRIVATE_H */
19 changes: 17 additions & 2 deletions poll/unix/epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
{
int ret;
apr_status_t rv = APR_SUCCESS;
apr_status_t wakeup_rv = APR_SUCCESS;

*num = 0;

Expand Down Expand Up @@ -289,8 +290,15 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
fdptr->desc_type == APR_POLL_FILE &&
fdptr->desc.f == pollset->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
rv = APR_EINTR;
if ( apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe) != APR_SUCCESS )
{
wakeup_rv = apr_pollset_wakeup_pipe_regenerate(pollset);
if ( wakeup_rv != APR_SUCCESS )
{
rv = wakeup_rv;
}
}
}
else {
pollset->p->result_set[j] = *fdptr;
Expand Down Expand Up @@ -460,7 +468,14 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
pollfd->desc_type == APR_POLL_FILE &&
pollfd->desc.f == pollcb->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe);
if ( apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe) != APR_SUCCESS )
{
rv = apr_pollcb_wakeup_pipe_regenerate(pollcb);
if ( rv != APR_SUCCESS )
{
return rv;
}
}
return APR_EINTR;
}

Expand Down
19 changes: 17 additions & 2 deletions poll/unix/kqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
int ret;
struct timespec tv, *tvptr;
apr_status_t rv = APR_SUCCESS;
apr_status_t wakeup_rv = APR_SUCCESS;

*num = 0;

Expand Down Expand Up @@ -286,8 +287,15 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
fd->desc_type == APR_POLL_FILE &&
fd->desc.f == pollset->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
rv = APR_EINTR;
if ( apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe) != APR_SUCCESS )
{
wakeup_rv = apr_pollset_wakeup_pipe_regenerate(pollset);
if ( wakeup_rv != APR_SUCCESS )
{
rv = wakeup_rv;
}
}
}
else {
pollset->p->result_set[j] = *fd;
Expand Down Expand Up @@ -473,7 +481,14 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
pollfd->desc_type == APR_POLL_FILE &&
pollfd->desc.f == pollcb->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe);
if ( apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe) != APR_SUCCESS )
{
rv = apr_pollcb_wakeup_pipe_regenerate(pollcb);
if ( rv != APR_SUCCESS )
{
return rv;
}
}
return APR_EINTR;
}

Expand Down
21 changes: 19 additions & 2 deletions poll/unix/poll.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
{
int ret;
apr_status_t rv = APR_SUCCESS;
apr_status_t wakeup_rv = APR_SUCCESS;

*num = 0;

Expand Down Expand Up @@ -275,8 +276,16 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
pollset->p->query_set[i].desc_type == APR_POLL_FILE &&
pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
rv = APR_EINTR;

if ( apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe) != APR_SUCCESS )
{
wakeup_rv = apr_pollset_wakeup_pipe_regenerate(pollset);
if ( wakeup_rv != APR_SUCCESS )
{
rv = wakeup_rv;
}
}
}
else {
pollset->p->result_set[j] = pollset->p->query_set[i];
Expand Down Expand Up @@ -422,7 +431,15 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
pollfd->desc_type == APR_POLL_FILE &&
pollfd->desc.f == pollcb->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe);

if ( apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe) != APR_SUCCESS )
{
rv = apr_pollcb_wakeup_pipe_regenerate(pollcb);
if ( rv != APR_SUCCESS )
{
return rv;
}
}
return APR_EINTR;
}

Expand Down
19 changes: 17 additions & 2 deletions poll/unix/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
apr_int32_t j;
pfd_elem_t *ep;
apr_status_t rv = APR_SUCCESS;
apr_status_t wakeup_rv = APR_SUCCESS;

*num = 0;
nget = 1;
Expand Down Expand Up @@ -411,8 +412,15 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
ep->pfd.desc_type == APR_POLL_FILE &&
ep->pfd.desc.f == pollset->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
rv = APR_EINTR;
if ( apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe) != APR_SUCCESS )
{
wakeup_rv = apr_pollset_wakeup_pipe_regenerate(pollset);
if ( wakeup_rv != APR_SUCCESS )
{
rv = wakeup_rv;
}
}
}
else {
pollset->p->result_set[j] = ep->pfd;
Expand Down Expand Up @@ -563,7 +571,14 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
pollfd->desc_type == APR_POLL_FILE &&
pollfd->desc.f == pollcb->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe);
if ( apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe) != APR_SUCCESS )
{
rv = apr_pollcb_wakeup_pipe_regenerate(pollcb);
if ( rv != APR_SUCCESS )
{
return rv;
}
}
return APR_EINTR;
}

Expand Down
12 changes: 11 additions & 1 deletion poll/unix/select.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
struct timeval tv, *tvptr;
fd_set readset, writeset, exceptset;
apr_status_t rv = APR_SUCCESS;
apr_status_t wakeup_rv = APR_SUCCESS;

*num = 0;

Expand Down Expand Up @@ -401,8 +402,17 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
else {
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe);
rv = APR_EINTR;

if ( apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe) != APR_SUCCESS )
{
wakeup_rv = apr_pollset_wakeup_pipe_regenerate(pollset);
if ( wakeup_rv != APR_SUCCESS )
{
rv = wakeup_rv;
}
}

continue;
}
else {
Expand Down
39 changes: 37 additions & 2 deletions poll/unix/wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,13 @@ apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)

/* Read and discard whatever is in the wakeup pipe.
*/
void apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe)
apr_status_t apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe)
{
char rb[512];
apr_size_t nr = sizeof(rb);
apr_status_t rv;

while (apr_file_read(wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
while ((rv = apr_file_read(wakeup_pipe[0], rb, &nr)) == APR_SUCCESS) {
/* Although we write just one byte to the other end of the pipe
* during wakeup, multiple threads could call the wakeup.
* So simply drain out from the input side of the pipe all
Expand All @@ -148,4 +149,38 @@ void apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe)
if (nr != sizeof(rb))
break;
}

return rv;
}

apr_status_t apr_pollset_wakeup_pipe_regenerate(apr_pollset_t *pollset)
{
apr_status_t rv;

apr_pollset_remove(pollset, &pollset->wakeup_pfd);
apr_poll_close_wakeup_pipe(pollset->wakeup_pipe);
if (!((rv = apr_poll_create_wakeup_pipe(pollset->pool,
&pollset->wakeup_pfd, pollset->wakeup_pipe)) == APR_SUCCESS &&
(rv = apr_pollset_add(pollset,
&pollset->wakeup_pfd)) == APR_SUCCESS)) {
return rv;
}

return APR_SUCCESS;
}

apr_status_t apr_pollcb_wakeup_pipe_regenerate(apr_pollcb_t *pollcb)
{
apr_status_t rv;

apr_pollcb_remove(pollcb, &pollcb->wakeup_pfd);
apr_poll_close_wakeup_pipe(pollcb->wakeup_pipe);
if (!((rv = apr_poll_create_wakeup_pipe(pollcb->pool,
&pollcb->wakeup_pfd, pollcb->wakeup_pipe)) == APR_SUCCESS &&
(rv = apr_pollcb_add(pollcb,
&pollcb->wakeup_pfd)) == APR_SUCCESS)) {
return rv;
}

return APR_SUCCESS;
}