diff options
Diffstat (limited to 'src/log_tail.c')
| -rw-r--r-- | src/log_tail.c | 45 |
1 files changed, 42 insertions, 3 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) { |
