diff options
| author | 2022-04-08 16:45:24 -0700 | |
|---|---|---|
| committer | 2022-04-08 16:45:24 -0700 | |
| commit | 12c265976561d7e28c50bad4736fbabb05756f1a (patch) | |
| tree | 963149321ed8fe724d974eb5b7fa449a4bffd8c3 | |
| parent | 8561dcdee486e696152e50c6c96f14941c897ce0 (diff) | |
| download | bun-12c265976561d7e28c50bad4736fbabb05756f1a.tar.gz bun-12c265976561d7e28c50bad4736fbabb05756f1a.tar.zst bun-12c265976561d7e28c50bad4736fbabb05756f1a.zip | |
[bun dev] Fix race condition in file watcher
| -rw-r--r-- | src/watcher.zig | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/src/watcher.zig b/src/watcher.zig index 40d2cf058..52c20bbb4 100644 --- a/src/watcher.zig +++ b/src/watcher.zig @@ -381,8 +381,6 @@ pub fn NewWatcher(comptime ContextType: type) type { pub fn flushEvictions(this: *Watcher) void { if (evict_list_i == 0) return; - this.mutex.lock(); - defer this.mutex.unlock(); defer evict_list_i = 0; // swapRemove messes up the order @@ -447,6 +445,9 @@ pub fn NewWatcher(comptime ContextType: type) type { watchevents[i].fromKEvent(event); } + this.mutex.lock(); + defer this.mutex.unlock(); + this.ctx.onFileUpdate(watchevents, this.changed_filepaths[0..watchevents.len], this.watchlist); } } else if (Environment.isLinux) { @@ -509,6 +510,10 @@ pub fn NewWatcher(comptime ContextType: type) type { last_event_id = all_events[i].index; } if (all_events.len == 0) continue :restart; + + this.mutex.lock(); + defer this.mutex.unlock(); + this.ctx.onFileUpdate(all_events[0 .. last_event_index + 1], this.changed_filepaths[0 .. name_off + 1], this.watchlist); remaining_events -= slice.len; } @@ -535,6 +540,9 @@ pub fn NewWatcher(comptime ContextType: type) type { package_json: ?*PackageJSON, comptime copy_file_path: bool, ) !void { + this.mutex.lock(); + defer this.mutex.unlock(); + if (this.indexOf(hash)) |index| { if (comptime FeatureFlags.atomic_file_watcher) { // On Linux, the file descriptor might be out of date. @@ -546,7 +554,7 @@ pub fn NewWatcher(comptime ContextType: type) type { return; } - try this.appendFile(fd, file_path, hash, loader, dir_fd, package_json, copy_file_path); + try this.appendFileMaybeLock(fd, file_path, hash, loader, dir_fd, package_json, copy_file_path, false); } fn appendFileAssumeCapacity( @@ -719,19 +727,19 @@ pub fn NewWatcher(comptime ContextType: type) type { hash: HashType, comptime copy_file_path: bool, ) !void { + this.mutex.lock(); + defer this.mutex.unlock(); + if (this.indexOf(hash) != null) { return; } - this.mutex.lock(); - defer this.mutex.unlock(); - try this.watchlist.ensureUnusedCapacity(this.allocator, 1); _ = try this.appendDirectoryAssumeCapacity(fd, file_path, hash, copy_file_path); } - pub fn appendFile( + pub fn appendFileMaybeLock( this: *Watcher, fd: StoredFileDescriptorType, file_path: string, @@ -740,9 +748,10 @@ pub fn NewWatcher(comptime ContextType: type) type { dir_fd: StoredFileDescriptorType, package_json: ?*PackageJSON, comptime copy_file_path: bool, + comptime lock: bool, ) !void { - this.mutex.lock(); - defer this.mutex.unlock(); + if (comptime lock) this.mutex.lock(); + defer if (comptime lock) this.mutex.unlock(); std.debug.assert(file_path.len > 1); const pathname = Fs.PathName.init(file_path); @@ -792,5 +801,18 @@ pub fn NewWatcher(comptime ContextType: type) type { } } } + + pub fn appendFile( + this: *Watcher, + fd: StoredFileDescriptorType, + file_path: string, + hash: HashType, + loader: options.Loader, + dir_fd: StoredFileDescriptorType, + package_json: ?*PackageJSON, + comptime copy_file_path: bool, + ) !void { + return appendFileMaybeLock(this, fd, file_path, hash, loader, dir_fd, package_json, copy_file_path, true); + } }; } |
