26 #if _POSIX_C_SOURCE >= 200112L
28 #include "../sigset.h"
50 #define LELY_NSIG _NSIG
63 #define IO_SIGSET_NODE_INIT(signo) \
78 } io_sigset_shared = {
80 PTHREAD_MUTEX_INITIALIZER,
85 static struct sigaction io_sigset_action[LELY_NSIG - 1];
87 static void io_sigset_handler(
int signo);
88 static void io_sigset_kill(
int signo);
89 static void io_sigset_process_all(
void);
90 static void io_sigset_process_sig(
int signo,
struct sllist *queue);
94 static size_t io_sigset_impl_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
95 static size_t io_sigset_impl_dev_abort(
io_dev_t *dev,
struct ev_task *task);
98 static const struct io_dev_vtbl io_sigset_impl_dev_vtbl = {
99 &io_sigset_impl_dev_get_ctx,
100 &io_sigset_impl_dev_get_exec,
101 &io_sigset_impl_dev_cancel,
102 &io_sigset_impl_dev_abort
107 static int io_sigset_impl_clear(
io_sigset_t *sigset);
108 static int io_sigset_impl_insert(
io_sigset_t *sigset,
int signo);
109 static int io_sigset_impl_remove(
io_sigset_t *sigset,
int signo);
110 static void io_sigset_impl_submit_wait(
115 &io_sigset_impl_get_dev,
116 &io_sigset_impl_clear,
117 &io_sigset_impl_insert,
118 &io_sigset_impl_remove,
119 &io_sigset_impl_submit_wait
123 static int io_sigset_impl_svc_notify_fork(
125 static void io_sigset_impl_svc_shutdown(
struct io_svc *svc);
128 static const struct io_svc_vtbl io_sigset_impl_svc_vtbl = {
129 &io_sigset_impl_svc_notify_fork,
130 &io_sigset_impl_svc_shutdown
148 unsigned shutdown : 1;
149 unsigned read_posted : 1;
150 unsigned wait_posted : 1;
151 unsigned pending : 1;
156 static void io_sigset_impl_watch_func(
struct io_poll_watch *watch,
int events);
157 static void io_sigset_impl_read_task_func(
struct ev_task *task);
158 static void io_sigset_impl_wait_task_func(
struct ev_task *task);
165 const struct io_svc *svc);
173 static int io_sigset_impl_do_insert(
struct io_sigset_impl *impl,
int signo);
174 static int io_sigset_impl_do_remove(
struct io_sigset_impl *impl,
int signo);
176 static size_t io_sigset_impl_do_abort_tasks(
struct io_sigset_impl *impl);
179 io_sigset_alloc(
void)
183 return impl ? &impl->sigset_vptr : NULL;
187 io_sigset_free(
void *ptr)
190 free(io_sigset_impl_from_sigset(ptr));
204 impl->dev_vptr = &io_sigset_impl_dev_vtbl;
205 impl->sigset_vptr = &io_sigset_impl_vtbl;
215 &io_sigset_impl_watch_func);
216 impl->fds[0] = impl->fds[1] = -1;
219 impl->
exec, &io_sigset_impl_read_task_func);
221 impl->
exec, &io_sigset_impl_wait_task_func);
224 if ((errsv = pthread_mutex_init(&impl->mtx, NULL)))
229 impl->read_posted = 0;
230 impl->wait_posted = 0;
235 for (
int i = 1; i < LELY_NSIG; i++)
239 if (io_sigset_impl_open(impl) == -1) {
251 pthread_mutex_destroy(&impl->mtx);
265 io_sigset_impl_svc_shutdown(&impl->svc);
268 io_sigset_impl_clear(sigset);
272 pthread_mutex_lock(&impl->mtx);
275 while (impl->read_posted || impl->wait_posted) {
276 if (io_sigset_impl_do_abort_tasks(impl))
278 pthread_mutex_unlock(&impl->mtx);
282 "io_sigset_fini() invoked with pending operations");
285 pthread_mutex_lock(&impl->mtx);
287 pthread_mutex_unlock(&impl->mtx);
291 io_sigset_impl_close(impl);
294 pthread_mutex_destroy(&impl->mtx);
309 io_sigset_t *tmp = io_sigset_init(sigset, poll, exec);
319 io_sigset_free((
void *)sigset);
329 io_sigset_fini(sigset);
330 io_sigset_free((
void *)sigset);
335 io_sigset_handler(
int signo)
337 io_sigset_shared.sig[signo - 1].pending = 1;
338 io_sigset_shared.pending = 1;
340 io_sigset_kill(signo);
344 io_sigset_kill(
int signo)
350 result = write(io_sigset_shared.sig[signo - 1].fd - 1,
"", 1);
351 }
while (result == -1 && errno == EINTR);
356 io_sigset_process_all(
void)
362 pthread_mutex_lock(&io_sigset_shared.mtx);
364 while (io_sigset_shared.pending) {
365 io_sigset_shared.pending = 0;
366 for (
int i = 1; i < LELY_NSIG; i++) {
367 if (io_sigset_shared.sig[i - 1].pending) {
368 io_sigset_shared.sig[i - 1].pending = 0;
369 io_sigset_process_sig(i, &queue);
374 pthread_mutex_unlock(&io_sigset_shared.mtx);
385 io_sigset_process_sig(
int signo,
struct sllist *queue)
387 for (
struct io_sigset_node *node = io_sigset_shared.sig[signo - 1].list;
388 node; node = node->
next) {
392 pthread_mutex_lock(&impl->mtx);
394 assert(node->watched);
395 if (!node->pending) {
398 if (!impl->wait_posted) {
399 impl->wait_posted = 1;
404 pthread_mutex_unlock(&impl->mtx);
410 io_sigset_impl_dev_get_ctx(
const io_dev_t *dev)
418 io_sigset_impl_dev_get_exec(
const io_dev_t *dev)
433 io_sigset_impl_pop(impl, &queue, task);
435 return io_sigset_wait_queue_post(&queue, 0);
446 io_sigset_impl_pop(impl, &queue, task);
454 const struct io_sigset_impl *impl = io_sigset_impl_from_sigset(sigset);
456 return &impl->dev_vptr;
466 int errsv = pthread_mutex_lock(&io_sigset_shared.mtx);
474 for (
int i = 1; i < LELY_NSIG; i++) {
475 if (io_sigset_impl_do_remove(impl, i) == -1)
480 pthread_mutex_unlock(&io_sigset_shared.mtx);
487 io_sigset_impl_insert(
io_sigset_t *sigset,
int signo)
491 if (signo <= 0 || signo >= LELY_NSIG) {
498 int errsv = pthread_mutex_lock(&io_sigset_shared.mtx);
505 int result = io_sigset_impl_do_insert(impl, signo);
508 pthread_mutex_unlock(&io_sigset_shared.mtx);
515 io_sigset_impl_remove(
io_sigset_t *sigset,
int signo)
519 if (signo <= 0 || signo >= LELY_NSIG) {
526 int errsv = pthread_mutex_lock(&io_sigset_shared.mtx);
533 int result = io_sigset_impl_do_remove(impl, signo);
536 pthread_mutex_unlock(&io_sigset_shared.mtx);
550 task->
exec = impl->exec;
554 pthread_mutex_lock(&impl->mtx);
556 if (impl->shutdown) {
558 pthread_mutex_unlock(&impl->mtx);
560 io_sigset_wait_post(wait, 0);
563 int post_wait = !impl->wait_posted && impl->pending;
565 impl->wait_posted = 1;
567 pthread_mutex_unlock(&impl->mtx);
585 if (io_sigset_impl_close(impl) == -1 && !result) {
590 if (io_sigset_impl_open(impl) == -1 && !result) {
600 io_sigset_impl_svc_shutdown(
struct io_svc *svc)
606 pthread_mutex_lock(&impl->mtx);
608 int shutdown = !impl->shutdown;
615 io_sigset_impl_do_abort_tasks(impl);
618 pthread_mutex_unlock(&impl->mtx);
623 io_sigset_impl_dev_cancel(dev, NULL);
627 io_sigset_impl_watch_func(
struct io_poll_watch *watch,
int events)
635 pthread_mutex_lock(&impl->mtx);
637 int post_read = !impl->read_posted;
638 impl->read_posted = 1;
640 pthread_mutex_unlock(&impl->mtx);
648 io_sigset_impl_read_task_func(
struct ev_task *task)
662 result = read(impl->fds[0], buf,
sizeof(buf));
665 }
while (result > 0 || (result == -1 && errno == EINTR));
666 if (result == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
670 io_sigset_process_all();
673 pthread_mutex_lock(&impl->mtx);
675 if (events && !impl->shutdown)
676 io_poll_watch(impl->poll, impl->fds[0], events, &impl->watch);
677 impl->read_posted = 0;
679 pthread_mutex_unlock(&impl->mtx);
686 io_sigset_impl_wait_task_func(
struct ev_task *task)
693 int signo = LELY_NSIG;
696 pthread_mutex_lock(&impl->mtx);
711 impl->pending = signo != LELY_NSIG;
712 int post_wait = impl->wait_posted = impl->pending
715 pthread_mutex_unlock(&impl->mtx);
719 io_sigset_wait_post(wait, signo);
726 io_sigset_impl_from_dev(
const io_dev_t *dev)
734 io_sigset_impl_from_sigset(
const io_sigset_t *sigset)
742 io_sigset_impl_from_svc(
const struct io_svc *svc)
757 pthread_mutex_lock(&impl->mtx);
764 pthread_mutex_unlock(&impl->mtx);
775 if (io_sigset_impl_close(impl) == -1) {
781 if (pipe2(impl->fds, O_CLOEXEC | O_NONBLOCK) == -1) {
783 if (pipe(impl->fds) == -1) {
791 if (impl->fds[1] - 1 > SIG_ATOMIC_MAX) {
793 goto error_sig_atomic;
823 goto error_poll_watch;
836 impl->fds[0] = impl->fds[1] = -1;
848 int fds[2] = { impl->fds[0], impl->fds[1] };
851 impl->fds[0] = impl->fds[1] = -1;
864 if (close(fds[1]) == -1 && !result) {
869 if (close(fds[0]) == -1 && !result) {
883 assert(signo < LELY_NSIG);
886 assert(node->signo == signo);
891 if (!io_sigset_shared.sig[signo - 1].list) {
892 assert(!io_sigset_shared.sig[signo - 1].fd);
893 io_sigset_shared.sig[signo - 1].fd = impl->fds[1] + 1;
895 struct sigaction act;
896 memset(&act, 0,
sizeof(act));
897 act.sa_handler = &io_sigset_handler;
898 sigemptyset(&act.sa_mask);
899 act.sa_flags = SA_RESTART;
901 if (sigaction(signo, &act, &io_sigset_action[signo - 1])
903 io_sigset_shared.sig[signo - 1].fd = 0;
908 node->next = io_sigset_shared.sig[signo - 1].list;
909 io_sigset_shared.sig[signo - 1].list = node;
912 assert(!node->pending);
922 assert(signo < LELY_NSIG);
925 assert(node->signo == signo);
932 while (*
pnode != node)
934 assert(*
pnode == node);
944 assert(io_sigset_shared.sig[signo - 1].fd == impl->fds[1] + 1);
945 if (
pnode == &io_sigset_shared.sig[signo - 1].list) {
946 result = sigaction(signo, &io_sigset_action[signo - 1],
949 io_sigset_shared.sig[signo - 1].fd = 0;
954 io_sigset_shared.sig[signo - 1].fd = impl->fds[1] + 1;
955 io_sigset_kill(signo);
974 impl->read_posted = 0;
983 impl->wait_posted = 0;
990 #endif // _POSIX_C_SOURCE >= 200112L