fix: log silent errors and fix scan_dir dangling snapshot key
This commit is contained in:
parent
046c304c60
commit
eb42d23fc8
5 changed files with 43 additions and 14 deletions
|
|
@ -220,6 +220,11 @@ fn callback(
|
|||
// a single event. Emit one change call per applicable flag so
|
||||
// callers see all relevant event types (e.g. created + modified).
|
||||
const ot: ObjectType = if (flags & kFSEventStreamEventFlagItemIsDir != 0) .dir else .file;
|
||||
// Handler errors are silently ignored: this callback runs on a GCD
|
||||
// dispatch thread managed by the OS, so there is no way to propagate
|
||||
// an error back to the caller. Stopping the stream from inside the
|
||||
// callback would require a separate signal channel and is not worth
|
||||
// the complexity; the stream will keep delivering future events.
|
||||
if (flags & kFSEventStreamEventFlagItemCreated != 0) {
|
||||
ctx.handler.change(path, .created, ot) catch {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,10 @@ pub fn Create(comptime variant: InterfaceType) type {
|
|||
.{ .fd = self.stop_pipe[0], .events = std.posix.POLL.IN, .revents = 0 },
|
||||
};
|
||||
while (true) {
|
||||
_ = std.posix.poll(&pfds, -1) catch return;
|
||||
_ = std.posix.poll(&pfds, -1) catch |e| {
|
||||
std.log.err("nightwatch: poll failed: {s}, stopping watch thread", .{@errorName(e)});
|
||||
return;
|
||||
};
|
||||
if (pfds[1].revents & std.posix.POLL.IN != 0) return; // stop signal
|
||||
if (pfds[0].revents & std.posix.POLL.IN != 0) {
|
||||
self.handle_read_ready(allocator) catch |e| {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,10 @@ fn thread_fn(self: *@This(), allocator: std.mem.Allocator) void {
|
|||
var events: [64]std.posix.Kevent = undefined;
|
||||
while (true) {
|
||||
// Block indefinitely until kqueue has events.
|
||||
const n = std.posix.kevent(self.kq, &.{}, &events, null) catch break;
|
||||
const n = std.posix.kevent(self.kq, &.{}, &events, null) catch |e| {
|
||||
std.log.err("nightwatch: kevent failed: {s}, stopping watch thread", .{@errorName(e)});
|
||||
break;
|
||||
};
|
||||
for (events[0..n]) |ev| {
|
||||
if (ev.filter == EVFILT_READ) return; // shutdown pipe readable, exit
|
||||
if (ev.filter != EVFILT_VNODE) continue;
|
||||
|
|
@ -170,7 +173,8 @@ fn thread_fn(self: *@This(), allocator: std.mem.Allocator) void {
|
|||
return;
|
||||
};
|
||||
} else if (ev.fflags & NOTE_WRITE != 0) {
|
||||
self.scan_dir(allocator, dir_path) catch {};
|
||||
self.scan_dir(allocator, dir_path) catch |e|
|
||||
std.log.err("nightwatch: scan_dir failed: {s}", .{@errorName(e)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -228,10 +232,16 @@ fn scan_dir(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8)
|
|||
}
|
||||
}
|
||||
|
||||
const gop = self.snapshots.getOrPut(allocator, dir_path) catch |e| {
|
||||
return e;
|
||||
};
|
||||
if (!gop.found_existing) gop.value_ptr.* = .empty;
|
||||
const gop = self.snapshots.getOrPut(allocator, dir_path) catch |e| return e;
|
||||
if (!gop.found_existing) {
|
||||
// dir_path points into a stack buffer; dupe it into allocator memory
|
||||
// so the snapshot key outlives the current thread_fn iteration.
|
||||
gop.key_ptr.* = allocator.dupe(u8, dir_path) catch |e| {
|
||||
_ = self.snapshots.remove(dir_path);
|
||||
return e;
|
||||
};
|
||||
gop.value_ptr.* = .empty;
|
||||
}
|
||||
const snapshot = gop.value_ptr;
|
||||
|
||||
var cit = current_files.iterator();
|
||||
|
|
|
|||
|
|
@ -97,7 +97,10 @@ fn thread_fn(self: *@This(), allocator: std.mem.Allocator) void {
|
|||
var events: [64]std.posix.Kevent = undefined;
|
||||
while (true) {
|
||||
// Block indefinitely until kqueue has events.
|
||||
const n = std.posix.kevent(self.kq, &.{}, &events, null) catch break;
|
||||
const n = std.posix.kevent(self.kq, &.{}, &events, null) catch |e| {
|
||||
std.log.err("nightwatch: kevent failed: {s}, stopping watch thread", .{@errorName(e)});
|
||||
break;
|
||||
};
|
||||
for (events[0..n]) |ev| {
|
||||
if (ev.filter == EVFILT_READ) return; // shutdown pipe readable, exit
|
||||
if (ev.filter != EVFILT_VNODE) continue;
|
||||
|
|
@ -151,7 +154,8 @@ fn thread_fn(self: *@This(), allocator: std.mem.Allocator) void {
|
|||
return;
|
||||
};
|
||||
} else if (ev.fflags & NOTE_WRITE != 0) {
|
||||
self.scan_dir(allocator, watch_path) catch {};
|
||||
self.scan_dir(allocator, watch_path) catch |e|
|
||||
std.log.err("nightwatch: scan_dir failed: {s}", .{@errorName(e)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -216,10 +220,16 @@ fn scan_dir(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8)
|
|||
}
|
||||
}
|
||||
|
||||
const gop = self.snapshots.getOrPut(allocator, dir_path) catch |e| {
|
||||
return e;
|
||||
};
|
||||
if (!gop.found_existing) gop.value_ptr.* = .empty;
|
||||
const gop = self.snapshots.getOrPut(allocator, dir_path) catch |e| return e;
|
||||
if (!gop.found_existing) {
|
||||
// dir_path points into a stack buffer; dupe it into allocator memory
|
||||
// so the snapshot key outlives the current thread_fn iteration.
|
||||
gop.key_ptr.* = allocator.dupe(u8, dir_path) catch |e| {
|
||||
_ = self.snapshots.remove(dir_path);
|
||||
return e;
|
||||
};
|
||||
gop.value_ptr.* = .empty;
|
||||
}
|
||||
const snapshot = gop.value_ptr;
|
||||
|
||||
var cit = current_files.iterator();
|
||||
|
|
|
|||
|
|
@ -198,7 +198,8 @@ fn thread_fn(
|
|||
// the `info` pointer (which points into w.buf) a dangling reference.
|
||||
const next_entry_offset = info.NextEntryOffset;
|
||||
watches_mutex.unlock();
|
||||
handler.change(full_path, event_type, object_type) catch {
|
||||
handler.change(full_path, event_type, object_type) catch |e| {
|
||||
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
||||
watches_mutex.lock();
|
||||
break;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue