handle EINTR while polling scripts/hooks
If poll() is interrupted by a signal, alpm was closing the socket it uses for listening to script/hook output. This would drop script output at the least and kill the script at the worst. Fixes FS#60396 Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com> Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
parent
9886566abb
commit
ac959bb9c6
3 changed files with 25 additions and 1 deletions
|
@ -665,6 +665,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[],
|
|||
ssize_t olen = 0, ilen = 0;
|
||||
nfds_t nfds = 2;
|
||||
struct pollfd fds[2], *child2parent = &(fds[0]), *parent2child = &(fds[1]);
|
||||
int poll_ret;
|
||||
|
||||
child2parent->fd = child2parent_pipefd[TAIL];
|
||||
child2parent->events = POLLIN;
|
||||
|
@ -685,7 +686,14 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[],
|
|||
#define STOP_POLLING(p) do { close(p->fd); p->fd = -1; } while(0)
|
||||
|
||||
while((child2parent->fd != -1 || parent2child->fd != -1)
|
||||
&& poll(fds, nfds, -1) > 0) {
|
||||
&& (poll_ret = poll(fds, nfds, -1)) != 0) {
|
||||
if(poll_ret == -1) {
|
||||
if(errno == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(child2parent->revents & POLLIN) {
|
||||
if(_alpm_chroot_read_from_child(handle, child2parent->fd,
|
||||
ibuf, &ilen, sizeof(ibuf)) != 0) {
|
||||
|
|
|
@ -150,6 +150,7 @@ TESTS += test/pacman/tests/replace102.py
|
|||
TESTS += test/pacman/tests/replace103.py
|
||||
TESTS += test/pacman/tests/replace104.py
|
||||
TESTS += test/pacman/tests/replace110.py
|
||||
TESTS += test/pacman/tests/scriptlet-signal-handling.py
|
||||
TESTS += test/pacman/tests/scriptlet-signal-reset.py
|
||||
TESTS += test/pacman/tests/scriptlet001.py
|
||||
TESTS += test/pacman/tests/scriptlet002.py
|
||||
|
|
15
test/pacman/tests/scriptlet-signal-handling.py
Normal file
15
test/pacman/tests/scriptlet-signal-handling.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
self.description = "Handle signal interrupts while running scriptlets/hooks"
|
||||
|
||||
p1 = pmpkg("dummy")
|
||||
p1.install['post_install'] = """
|
||||
kill -INT $PPID # send an arbitrary signal that pacman catches
|
||||
sleep 1 # give alpm time to close the socket if EINTR was not handled
|
||||
echo to-parent # if the interrupt is not handled this will die with SIGPIPE
|
||||
echo success > interrupt_was_handled
|
||||
"""
|
||||
self.addpkg(p1)
|
||||
|
||||
self.args = "-U %s" % p1.filename()
|
||||
|
||||
self.addrule("PACMAN_RETCODE=0")
|
||||
self.addrule("FILE_EXIST=interrupt_was_handled")
|
Loading…
Add table
Reference in a new issue