2 * uloop - event loop implementation
4 * Copyright (C) 2010-2016 Felix Fietkau <nbd@openwrt.org>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/signalfd.h>
22 * FIXME: uClibc < 0.9.30.3 does not define EPOLLRDHUP for Linux >= 2.6.17
25 #define EPOLLRDHUP 0x2000
29 uloop_signal_fd_cb(struct uloop_fd
*fd
, unsigned int events
)
31 struct signalfd_siginfo fdsi
;
35 ret
= read(fd
->fd
, &fdsi
, sizeof(fdsi
));
36 if (ret
< 0 && errno
== EINTR
)
39 if (ret
!= sizeof(fdsi
))
42 uloop_handle_signal(fdsi
.ssi_signo
);
46 uloop_setup_signalfd(bool add
)
48 static struct uloop_fd sfd
= {
49 .cb
= uloop_signal_fd_cb
51 static sigset_t prev_mask
;
60 uloop_fd_delete(&sfd
);
61 sigprocmask(SIG_BLOCK
, &prev_mask
, NULL
);
63 sigaddset(&mask
, SIGQUIT
);
64 sigaddset(&mask
, SIGINT
);
65 sigaddset(&mask
, SIGTERM
);
66 sigaddset(&mask
, SIGCHLD
);
67 sigprocmask(SIG_BLOCK
, &mask
, &prev_mask
);
70 uloop_fd_add(&sfd
, ULOOP_READ
| ULOOP_EDGE_TRIGGER
);
73 if (signalfd(signal_fd
, &mask
, SFD_NONBLOCK
| SFD_CLOEXEC
) < 0) {
74 sigprocmask(SIG_BLOCK
, &prev_mask
, NULL
);
88 poll_fd
= epoll_create(32);
92 fcntl(poll_fd
, F_SETFD
, fcntl(poll_fd
, F_GETFD
) | FD_CLOEXEC
);
95 signal_fd
= signalfd(-1, &mask
, SFD_NONBLOCK
| SFD_CLOEXEC
);
100 static int register_poll(struct uloop_fd
*fd
, unsigned int flags
)
102 struct epoll_event ev
;
103 int op
= fd
->registered
? EPOLL_CTL_MOD
: EPOLL_CTL_ADD
;
105 memset(&ev
, 0, sizeof(struct epoll_event
));
107 if (flags
& ULOOP_READ
)
108 ev
.events
|= EPOLLIN
| EPOLLRDHUP
;
110 if (flags
& ULOOP_WRITE
)
111 ev
.events
|= EPOLLOUT
;
113 if (flags
& ULOOP_EDGE_TRIGGER
)
114 ev
.events
|= EPOLLET
;
120 return epoll_ctl(poll_fd
, op
, fd
->fd
, &ev
);
123 static struct epoll_event events
[ULOOP_MAX_EVENTS
];
125 static int __uloop_fd_delete(struct uloop_fd
*sock
)
128 return epoll_ctl(poll_fd
, EPOLL_CTL_DEL
, sock
->fd
, 0);
131 static int uloop_fetch_events(int timeout
)
135 nfds
= epoll_wait(poll_fd
, events
, ARRAY_SIZE(events
), timeout
);
136 for (n
= 0; n
< nfds
; ++n
) {
137 struct uloop_fd_event
*cur
= &cur_fds
[n
];
138 struct uloop_fd
*u
= events
[n
].data
.ptr
;
145 if (events
[n
].events
& (EPOLLERR
|EPOLLHUP
)) {
147 if (!(u
->flags
& ULOOP_ERROR_CB
))
151 if(!(events
[n
].events
& (EPOLLRDHUP
|EPOLLIN
|EPOLLOUT
|EPOLLERR
|EPOLLHUP
))) {
156 if(events
[n
].events
& EPOLLRDHUP
)
159 if(events
[n
].events
& EPOLLIN
)
162 if(events
[n
].events
& EPOLLOUT
)