Fix: reopen fifo when writer closes

This commit is contained in:
Nikita Ivanov 2022-06-01 02:47:37 +05:00
parent 6690c5048d
commit b28bd33f41
No known key found for this signature in database
GPG Key ID: 6E656AC5B97B5133

View File

@ -40,17 +40,27 @@ static int register_signal(int sig, __sighandler_t handler)
return OK; return OK;
} }
static int listen(int fifo_fd) static int open_fifo(int *fd, char *f)
{
ERRCHK_RET((*fd = open(f, O_RDONLY | O_NONBLOCK)) == -1, FUNCFAILED("open"), ERRNOS);
return OK;
}
static int listen(char *fifo)
{ {
int ret = OK; int ret = OK;
struct pollfd pollfd = { .fd = -1, .events = POLLIN };
ERRCHK_GOTO_OK(open_fifo(&pollfd.fd, fifo), ret, exit);
/* /*
* We don't register actual handlers because when one occures, * We don't register actual handlers because when one occures,
* poll() returns 0, which will break the loop and a normal * poll() returns 0, which will break the loop and a normal
* exit will happen. * exit will happen.
*/ */
ERRCHK_GOTO_OK(register_signal(SIGINT, sig_handler_exit), ret, exit); ERRCHK_GOTO_OK(register_signal(SIGINT, sig_handler_exit), ret, fifo);
ERRCHK_GOTO_OK(register_signal(SIGTERM, sig_handler_exit), ret, exit); ERRCHK_GOTO_OK(register_signal(SIGTERM, sig_handler_exit), ret, fifo);
int pipe_fds[2]; int pipe_fds[2];
ERRCHK_GOTO(pipe(pipe_fds) == -1, ret, signal, FUNCFAILED("pipe"), ERRNOS); ERRCHK_GOTO(pipe(pipe_fds) == -1, ret, signal, FUNCFAILED("pipe"), ERRNOS);
@ -66,8 +76,6 @@ static int listen(int fifo_fd)
if (ret != OK) if (ret != OK)
goto close; goto close;
struct pollfd pollfd = { .fd = fifo_fd, .events = POLLIN };
/* /*
* "Listen" to fifo and redirect all the input to ueberzug * "Listen" to fifo and redirect all the input to ueberzug
* instance. * instance.
@ -80,15 +88,23 @@ static int listen(int fifo_fd)
if (poll_ret == 0) if (poll_ret == 0)
continue; continue;
static char buf[1024]; if (pollfd.revents & POLLIN) {
while ((len = read(fifo_fd, buf, LEN(buf))) > 0) { static char buf[1024];
/* But first byte equal to 0 means "exit" */ while ((len = read(pollfd.fd, buf, LEN(buf))) > 0) {
if (buf[0] == 0) /* But first byte equal to 0 means "exit" */
goto close; if (buf[0] == 0)
write(pipe_fds[1], buf, len); goto close;
write(pipe_fds[1], buf, len);
}
}
if (pollfd.revents & POLLHUP) {
close(pollfd.fd);
ERRCHK_GOTO_OK(open_fifo(&pollfd.fd, fifo), ret, exit);
} }
} }
ERRCHK_GOTO(poll_ret < 0, ret, close, FUNCFAILED("poll"), ERRNOS); ERRCHK_GOTO(poll_ret < 0, ret, close, FUNCFAILED("poll"), ERRNOS);
close: close:
@ -99,6 +115,10 @@ signal:
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL); signal(SIGTERM, SIG_DFL);
fifo:
if (pollfd.fd >= 0)
close(pollfd.fd);
exit: exit:
return ret; return ret;
} }
@ -122,6 +142,7 @@ int server_listen(char const *id_s)
ERRCHK_GOTO_OK(check_ueberzug(&exitcode), ret, exit); ERRCHK_GOTO_OK(check_ueberzug(&exitcode), ret, exit);
if (exitcode == 127) { if (exitcode == 127) {
ret = ERR;
print_error("ueberzug is not installed"); print_error("ueberzug is not installed");
goto exit; goto exit;
} }
@ -129,17 +150,16 @@ int server_listen(char const *id_s)
char fifo[FIFO_FILENAME_SIZE]; char fifo[FIFO_FILENAME_SIZE];
get_fifo_name(fifo, LEN(fifo), id_s); get_fifo_name(fifo, LEN(fifo), id_s);
ERRCHK_GOTO(mkfifo(fifo, 0600) == -1 && errno != EEXIST, ret, exit, if (mkfifo(fifo, 0600) == -1) {
FUNCFAILED("mkfifo"), ERRNOS); if (errno == EEXIST)
print_errorf("server with id %s is already running or fifo %s still exists", id_s, fifo);
else
PRINTINTERR(FUNCFAILED("mkfifo"), ERRNOS);
ret = ERR;
goto exit;
}
int fifo_fd; ERRCHK_GOTO_OK(listen(fifo), ret, fifo);
ERRCHK_GOTO((fifo_fd = open(fifo, O_RDONLY | O_NONBLOCK)) == -1, ret, fifo,
FUNCFAILED("open"), ERRNOS);
ERRCHK_GOTO_OK(listen(fifo_fd), ret, fifo_fd);
fifo_fd:
close(fifo_fd);
fifo: fifo:
if (remove(fifo) == -1 && errno != ENOENT) if (remove(fifo) == -1 && errno != ENOENT)