Skip to content

Commit 9bbd0ba

Browse files
committed
fix deadlock when building with -Dsingle-threaded
Single threaded mode seems the have been bugged for a while...
1 parent 04dfe2a commit 9bbd0ba

File tree

1 file changed

+30
-18
lines changed

1 file changed

+30
-18
lines changed

src/DocumentStore.zig

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -643,11 +643,13 @@ pub fn getBuildFile(self: *DocumentStore, uri: Uri) ?*BuildFile {
643643
fn getOrLoadBuildFile(self: *DocumentStore, uri: Uri) ?*BuildFile {
644644
if (self.getBuildFile(uri)) |build_file| return build_file;
645645

646-
self.lock.lock();
647-
defer self.lock.unlock();
646+
const new_build_file: *BuildFile = blk: {
647+
self.lock.lock();
648+
defer self.lock.unlock();
649+
650+
const gop = self.build_files.getOrPut(self.allocator, uri) catch return null;
651+
if (gop.found_existing) return gop.value_ptr.*;
648652

649-
const gop = self.build_files.getOrPut(self.allocator, uri) catch return null;
650-
if (!gop.found_existing) {
651653
gop.value_ptr.* = self.allocator.create(BuildFile) catch |err| {
652654
self.build_files.swapRemoveAt(gop.index);
653655
log.debug("Failed to load build file {s}: {}", .{ uri, err });
@@ -661,9 +663,16 @@ fn getOrLoadBuildFile(self: *DocumentStore, uri: Uri) ?*BuildFile {
661663
return null;
662664
};
663665
gop.key_ptr.* = gop.value_ptr.*.uri;
666+
break :blk gop.value_ptr.*;
667+
};
668+
669+
// this code path is only reached when the build file is new
670+
671+
if (std.process.can_spawn) {
672+
self.invalidateBuildFile(new_build_file.uri);
664673
}
665674

666-
return gop.value_ptr.*;
675+
return new_build_file;
667676
}
668677

669678
/// **Thread safe** takes an exclusive lock
@@ -737,25 +746,32 @@ pub fn refreshDocument(self: *DocumentStore, uri: Uri, new_text: [:0]const u8) !
737746

738747
/// Invalidates a build files.
739748
/// **Thread safe** takes a shared lock
740-
pub fn invalidateBuildFile(self: *DocumentStore, build_file_uri: Uri) error{OutOfMemory}!void {
749+
pub fn invalidateBuildFile(self: *DocumentStore, build_file_uri: Uri) void {
741750
comptime std.debug.assert(std.process.can_spawn);
742751

743752
if (self.config.zig_exe_path == null) return;
744753
if (self.config.build_runner_path == null) return;
745754
if (self.config.global_cache_path == null) return;
746755

747-
const uri = try self.allocator.dupe(u8, build_file_uri);
748-
errdefer self.allocator.free(uri);
749-
750756
if (builtin.single_threaded) {
751-
self.invalidateBuildFileWorker(uri);
752-
} else {
753-
try self.thread_pool.spawn(invalidateBuildFileWorker, .{ self, uri });
757+
self.invalidateBuildFileWorker(build_file_uri, false);
758+
return;
754759
}
760+
761+
const duped_uri = self.allocator.dupe(u8, build_file_uri) catch {
762+
self.invalidateBuildFileWorker(build_file_uri, false);
763+
return;
764+
};
765+
766+
self.thread_pool.spawn(invalidateBuildFileWorker, .{ self, duped_uri, true }) catch {
767+
self.allocator.free(duped_uri);
768+
self.invalidateBuildFileWorker(build_file_uri, false);
769+
return;
770+
};
755771
}
756772

757-
fn invalidateBuildFileWorker(self: *DocumentStore, build_file_uri: Uri) void {
758-
defer self.allocator.free(build_file_uri);
773+
fn invalidateBuildFileWorker(self: *DocumentStore, build_file_uri: Uri, is_build_file_uri_owned: bool) void {
774+
defer if (is_build_file_uri_owned) self.allocator.free(build_file_uri);
759775

760776
const build_config = loadBuildConfiguration(self, build_file_uri) catch |err| {
761777
log.err("Failed to load build configuration for {s} (error: {})", .{ build_file_uri, err });
@@ -1097,10 +1113,6 @@ fn createBuildFile(self: *DocumentStore, uri: Uri) error{OutOfMemory}!BuildFile
10971113
}
10981114
}
10991115

1100-
if (std.process.can_spawn) {
1101-
try self.invalidateBuildFile(build_file.uri);
1102-
}
1103-
11041116
log.info("Loaded build file '{s}'", .{build_file.uri});
11051117

11061118
return build_file;

0 commit comments

Comments
 (0)