diff options
| author | auric <auric7@protonmail.com> | 2026-02-22 18:18:36 -0600 |
|---|---|---|
| committer | auric <auric7@protonmail.com> | 2026-02-22 18:19:11 -0600 |
| commit | b2dd175b900556fb6d7bb2928cad53e9d73fc6a7 (patch) | |
| tree | 5bdc716b569cc0ec2ad9b68efe2d68de2f0b4b93 /src | |
| parent | 52f92ea70f74008d82d21fef5085fb7380314ea1 (diff) | |
Fix log tail rotation handling and SIGHUP cleanup
- Detect IN_MOVE_SELF/IN_DELETE_SELF events in log_tail_handle and
re-open the watched path so srcds log rotation is followed correctly
- Parse inotify events rather than blindly draining them
- Call log_tail_cleanup() before log_tail_init() on SIGHUP to prevent
fd leaks on reload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/log_tail.c | 45 | ||||
| -rw-r--r-- | src/main.c | 7 |
2 files changed, 46 insertions, 6 deletions
diff --git a/src/log_tail.c b/src/log_tail.c index d352f8f..973cc0b 100644 --- a/src/log_tail.c +++ b/src/log_tail.c @@ -47,7 +47,8 @@ void log_tail_init(void) { close(log_fd); continue; } - int wd = inotify_add_watch(ifd, path, IN_MODIFY); + int wd = inotify_add_watch(ifd, path, + IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF); if (wd < 0) { log_warn("log_tail: inotify_add_watch %s: %s", path, strerror(errno)); @@ -95,9 +96,22 @@ static LogWatch *watch_for_inotify_fd(int fd) { void log_tail_handle(int inotify_fd) { LogWatch *w = watch_for_inotify_fd(inotify_fd); if (!w) return; + + /* Parse inotify events — detect log rotation (file moved or deleted) */ char evbuf[4096]; - while (read(inotify_fd, evbuf, sizeof(evbuf)) > 0) - ; + int rotated = 0; + ssize_t nread; + while ((nread = read(inotify_fd, evbuf, sizeof(evbuf))) > 0) { + char *p = evbuf; + while (p < evbuf + nread) { + struct inotify_event *ie = (struct inotify_event *)p; + if (ie->mask & (IN_MOVE_SELF | IN_DELETE_SELF)) + rotated = 1; + p += sizeof(struct inotify_event) + ie->len; + } + } + + /* Drain any new data from the current log fd before re-opening */ char buf[RING_BUF_LINE_MAX]; ssize_t n; while ((n = read(w->log_fd, buf, sizeof(buf) - 1)) > 0) { @@ -105,6 +119,31 @@ void log_tail_handle(int inotify_fd) { ring_push(w->unit->output, buf, (int)n); client_broadcast_output(w->unit->name, buf, 0); } + + if (!rotated) return; + + /* Log file was rotated — re-open the path to follow the new file */ + inotify_rm_watch(w->inotify_fd, w->watch_wd); + close(w->log_fd); + w->log_fd = -1; + + int log_fd = open(w->path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (log_fd < 0) { + log_warn("log_tail: cannot re-open %s after rotation: %s", + w->path, strerror(errno)); + return; + } + int wd = inotify_add_watch(w->inotify_fd, w->path, + IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF); + if (wd < 0) { + log_warn("log_tail: inotify_add_watch after rotation %s: %s", + w->path, strerror(errno)); + close(log_fd); + return; + } + w->log_fd = log_fd; + w->watch_wd = wd; + log_info("log_tail: re-opened %s after rotation", w->path); } void log_tail_cleanup(void) { @@ -59,10 +59,11 @@ static void handle_signal(void) { case SIGHUP: log_info("SIGHUP received — reloading units"); + log_tail_cleanup(); /* Reload unit descriptors. Existing runtime state is preserved. */ g.unit_count = 0; unit_load_all(); - log_tail_init(); + log_tail_init(); break; } } @@ -206,8 +207,6 @@ int main(int argc, char *argv[]) { ev.data.fd = g.signal_fd; epoll_ctl(g.epoll_fd, EPOLL_CTL_ADD, g.signal_fd, &ev); - log_tail_init(); - /* Load unit descriptors */ if (unit_load_all() < 0) { log_error("Failed to load units"); @@ -215,6 +214,8 @@ int main(int argc, char *argv[]) { return 1; } + log_tail_init(); + /* Set up listening socket */ g.listen_fd = client_listen(); if (g.listen_fd < 0) { |
