diff --git a/ext/standard/tests/poll/poll_stream_add_unpollable.phpt b/ext/standard/tests/poll/poll_stream_add_unpollable.phpt new file mode 100644 index 000000000000..f38618e622d8 --- /dev/null +++ b/ext/standard/tests/poll/poll_stream_add_unpollable.phpt @@ -0,0 +1,36 @@ +--TEST-- +Io\Poll: epoll reports a handle it cannot watch as unsupported +--SKIPIF-- +getBackend()->name) { + die("skip requires the epoll backend\n"); +} +?> +--FILE-- + fopen(__FILE__, 'r'), '/dev/null' => fopen('/dev/null', 'r')] as $label => $stream) { + try { + $ctx->add(new StreamPollHandle($stream), [Io\Poll\Event::Read]); + echo "$label: added\n"; + } catch (Io\Poll\FailedHandleAddException $e) { + printf("%s: %s, code %s\n", $label, $e->getMessage(), + Io\Poll\FailedPollOperationException::ERROR_NOSUPPORT === $e->getCode() ? 'ERROR_NOSUPPORT' : $e->getCode()); + } + fclose($stream); +} + +// a pollable handle still works +[$r, $w] = pt_new_socket_pair(); +$ctx->add(new StreamPollHandle($r), [Io\Poll\Event::Read]); +echo "socket: added\n"; +?> +--EXPECT-- +regular file: Failed to add handle, code ERROR_NOSUPPORT +/dev/null: Failed to add handle, code ERROR_NOSUPPORT +socket: added diff --git a/main/poll/poll_backend_epoll.c b/main/poll/poll_backend_epoll.c index 394b0dc52446..1cc05b3005e5 100644 --- a/main/poll/poll_backend_epoll.c +++ b/main/poll/poll_backend_epoll.c @@ -125,7 +125,13 @@ static zend_result epoll_backend_add(php_poll_ctx *ctx, int fd, uint32_t events, ev.data.ptr = data; if (epoll_ctl(backend_data->epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) { - php_poll_set_error(ctx, (errno == EEXIST) ? PHP_POLL_ERR_EXISTS : PHP_POLL_ERR_SYSTEM); + /* EPERM means the target file does not implement polling, which is the case + * for regular files and for character devices such as /dev/null. */ + if (errno == EPERM) { + php_poll_set_error(ctx, PHP_POLL_ERR_NOSUPPORT); + } else { + php_poll_set_current_errno_error(ctx); + } return FAILURE; } backend_data->fd_count++; @@ -142,7 +148,7 @@ static zend_result epoll_backend_modify(php_poll_ctx *ctx, int fd, uint32_t even ev.data.ptr = data; if (epoll_ctl(backend_data->epoll_fd, EPOLL_CTL_MOD, fd, &ev) == -1) { - php_poll_set_error(ctx, (errno == ENOENT) ? PHP_POLL_ERR_NOTFOUND : PHP_POLL_ERR_SYSTEM); + php_poll_set_current_errno_error(ctx); return FAILURE; } @@ -154,7 +160,7 @@ static zend_result epoll_backend_remove(php_poll_ctx *ctx, int fd) epoll_backend_data_t *backend_data = (epoll_backend_data_t *) ctx->backend_data; if (epoll_ctl(backend_data->epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1) { - php_poll_set_error(ctx, (errno == ENOENT) ? PHP_POLL_ERR_NOTFOUND : PHP_POLL_ERR_SYSTEM); + php_poll_set_current_errno_error(ctx); return FAILURE; } backend_data->fd_count--;