summaryrefslogtreecommitdiff
path: root/src/log_tail.c
diff options
context:
space:
mode:
authorauric <auric@japegames.com>2026-02-22 18:18:36 -0600
committerauric <auric@japegames.com>2026-02-22 18:19:11 -0600
commit9d113e9bb8b7d57b4a088d4991674ff068ac56bf (patch)
tree5bdc716b569cc0ec2ad9b68efe2d68de2f0b4b93 /src/log_tail.c
parent52f92ea70f74008d82d21fef5085fb7380314ea1 (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/log_tail.c')
-rw-r--r--src/log_tail.c45
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) {