On 11/14/19 8:27 AM, Jens Axboe wrote: > On 11/14/19 8:20 AM, Jens Axboe wrote: >> On 11/14/19 8:19 AM, Rasmus Villemoes wrote: >>> On 14/11/2019 16.09, Jens Axboe wrote: >>>> On 11/14/19 7:12 AM, Rasmus Villemoes wrote: >>> >>>>> So, I can't really think of anybody that might be relying on inheriting >>>>> a signalfd instead of just setting it up in the child, but changing the >>>>> semantics of it now seems rather dangerous. Also, I _can_ imagine >>>>> threads in a process sharing a signalfd (initial thread sets it up and >>>>> blocks the signals, all threads subsequently use that same fd), and for >>>>> that case it would be wrong for one thread to dequeue signals directed >>>>> at the initial thread. Plus the lifetime problems. >>>> >>>> What if we just made it specific SFD_CLOEXEC? >>> >>> O_CLOEXEC can be set and removed afterwards. Sure, we're far into >>> "nobody does that" land, but having signalfd() have wildly different >>> semantics based on whether it was initially created with O_CLOEXEC seems >>> rather dubious. >>> >>> I don't want to break >>>> existing applications, even if the use case is nonsensical, but it is >>>> important to allow signalfd to be properly used with use cases that are >>>> already in the kernel (aio with IOCB_CMD_POLL, io_uring with >>>> IORING_OP_POLL_ADD). Alternatively, if need be, we could add a specific >>>> SFD_ flag for this. >>> >>> Yeah, if you want another signalfd flavour, adding it via a new SFD_ >>> flag seems the way to go. Though I can't imagine the resulting code >>> would be very pretty. >> >> Well, it's currently _broken_ for the listed in-kernel use cases, so >> I think making it work is the first priority here. > > How about something like this, then? Not tested. Tested, works for me. Here's the test case I used. We setup a signalfd with SIGALRM, and arm a timer for 100msec. Then we queue a poll for the signalfd, and wait for that to complete with a timeout of 1 second. If we time out waiting for the completion, we failed. If we do get a completion but we don't have POLLIN set, we failed. #include <unistd.h> #include <sys/signalfd.h> #include <sys/poll.h> #include <sys/time.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <liburing.h> #define SFD_TASK 00000001 int main(int argc, char *argv[]) { struct __kernel_timespec ts; struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; struct io_uring ring; struct itimerval itv; sigset_t mask; int sfd, ret; sigemptyset(&mask); sigaddset(&mask, SIGALRM); sigprocmask(SIG_BLOCK, &mask, NULL); sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC | SFD_TASK); if (sfd < 0) { if (errno == EINVAL) { printf("Not supported\n"); return 0; } perror("signalfd"); return 1; } memset(&itv, 0, sizeof(itv)); itv.it_value.tv_sec = 0; itv.it_value.tv_usec = 100000; setitimer(ITIMER_REAL, &itv, NULL); io_uring_queue_init(32, &ring, 0); sqe = io_uring_get_sqe(&ring); io_uring_prep_poll_add(sqe, sfd, POLLIN); io_uring_submit(&ring); ts.tv_sec = 1; ts.tv_nsec = 0; ret = io_uring_wait_cqe_timeout(&ring, &cqe, &ts); if (ret < 0) { fprintf(stderr, "Timed out waiting for cqe\n"); ret = 1; } else { if (cqe->res < 0) { fprintf(stderr, "cqe failed with %d\n", cqe->res); ret = 1; } else if (!(cqe->res & POLLIN)) { fprintf(stderr, "POLLIN not set in result mask?\n"); ret = 1; } else { ret = 0; } } io_uring_cqe_seen(&ring, cqe); io_uring_queue_exit(&ring); close(sfd); return ret; } -- Jens Axboe