When uloop_process_add() is called outside of uloop_run(), i.e. not
from a callback (which is the case of at least utrace and ujail),
child events can be missed. The reason is that when SIGCHILD handler
is installed in uloop_run(), after the uloop_process_add() is called,
then an initial signal could be missed.
Commit 4e3a47a ("uloop: use a waker for notifying sigchld and loop
cancel events", 2016-06-09) solved a similar problem and introduced
uloop_init() but forgot to move a call to uloop_setup_signals() there.
This is what this commit does.
Now, uloop_process_add() can be called any time after uloop_init()
without missing any event.
Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>
Acked-by: Yousong Zhou <yszhou4tech@gmail.com>
Variable confusion was breaking timers
Fixes: 368fd26458 ("uloop: allow specifying a timeout for uloop_run()")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This can be useful for cleanup with pending timers, or for hooking into
existing code that does not use uloop
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Recent glibc warns if result of read() or write() is unused.
Added a retry in case of EINTR, all other faults are silently discarded.
Signed-off-by: Eyal Birger <eyal.birger@gmail.com>
-----
- I was not able to reproduce the EINTR case, but it seems to be the right
thing to do
- Retrying on EAGAIN in this case would be weird as there is no one to read
from the other end of the pipe. We could call waker_consume() directly but
since the size of the message is just one byte, I think this would be dead
code
When a process quits in response to a signal it handles, it should to so
be re-sending the signal to itself. This especially important for SIGINT,
as is explained in [1].
uloop currently hides the reason for quitting uloop_run(). Fix this by
returning the signal that caused the loop to quit (or 0 when uloop_end()
was used), so a program using loop an comply with [1].
[1] https://www.cons.org/cracauer/sigint.html
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Fix a race condition when do_sigchld, uloop_cancelled were set just
before epoll_wait(timeout=-1), resulting the loop stuck in the syscall
without noticing the events just happened
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Most app don't want to crash because of unhandled SIGPIPE. It could
happen is such trivial situations like writing to socket.
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
In some conditions, an application is interested in errors happening
on a file descriptor and might be able to resolve the issue in the
callback function.
This patch adds a flag to notify the uloop framework that errors
should be passed to the callback function, instead of silently
removing the fd from the polling set.
Signed-off-by: Karl Vogel <karl.vogel@gmail.com>
uloop_run calls uloop_setup_signals() to set up signal handling before the while
loop, but does not remove the signal handling after the loop has ended. This can
cause problems for for example applications using the ubus file descriptor in
their own event loops, and perhaps with their own signal handling.
This patch stores the signal handle that was in place when the initial
uloop_run() call was made, and restores the handle when this call returns.
For recursive calls, the signal handler is not updated.
One use-case I experienced was an application that subscribed to several ubus
objects and used the ubus file descriptor in its own event loop. Even though
ubus_register_subscriber() (which calls uloop_run()) had returned, the signal
handler was not removed. This caused SIGINT not to be caught by the application.
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
When a fd gets deleted internally due to errors, fd->registered gets set
to false before events are moved to the staging array.
This leads to pending events not getting cleared properly when the fd
user finally calls uloop_fd_del.
Fix this by moving the check down and always checking for pending
events.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
uloop timeouts are calculated based on a time value that was fetched
before any callbacks were executed. Hence, the next timeout is off by
the time the callback execution took which can lead to strange side
effects.
Fix this by calculating the next timeout based on a fresh time value.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
With multiple recursive calls to uloop_run, the callback for the same fd
can be run multiple times from different levels in the stack.
Prevent this by tracking the stack of uloop_fd callbacks and buffering new
incoming events for fds already on the stack.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Recursive calls to uloop_run() need to process already fetched events
first, before running kqueue/epoll to get more.
The state of cur_fd/cur_nfds and the event list needs to be maintained
properly to prevent accidental running of events pointing at deleted
uloop_fd structs.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Sometimes after re-arming a fd, an initial event for reads is not generated,
even though there is data pending. Work around this by making the trigger
level-triggered first, then switching to edge trigger after processing the first
event.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>