| ... | @@ -434,24 +434,29 @@ pub const Manifest = struct { | ... | @@ -434,24 +434,29 @@ pub const Manifest = struct { |
| 434 | } | 434 | } |
| 435 | } | 435 | } |
| 436 | } else { | 436 | } else { |
| 437 | if (self.cache.manifest_dir.createFile(&manifest_file_path, .{ | 437 | while (true) { |
| 438 | .read = true, | 438 | if (self.cache.manifest_dir.createFile(&manifest_file_path, .{ |
| 439 | .truncate = false, | 439 | .read = true, |
| 440 | .lock = .Exclusive, | 440 | .truncate = false, |
| 441 | .lock_nonblocking = self.want_shared_lock, | 441 | .lock = .Exclusive, |
| 442 | })) |manifest_file| { | 442 | .lock_nonblocking = self.want_shared_lock, |
| 443 | self.manifest_file = manifest_file; | 443 | })) |manifest_file| { |
| 444 | self.have_exclusive_lock = true; | 444 | self.manifest_file = manifest_file; |
| 445 | } else |err| switch (err) { | 445 | self.have_exclusive_lock = true; |
| 446 | // There are no dir components, so you would think that this was | 446 | break; |
| 447 | // unreachable, however we have observed on macOS two processes racing | 447 | } else |err| switch (err) { |
| 448 | // to do openat() with O_CREAT manifest in ENOENT. | 448 | error.WouldBlock => { |
| 449 | error.WouldBlock, error.FileNotFound => { | 449 | self.manifest_file = try self.cache.manifest_dir.openFile(&manifest_file_path, .{ |
| 450 | self.manifest_file = try self.cache.manifest_dir.openFile(&manifest_file_path, .{ | 450 | .lock = .Shared, |
| 451 | .lock = .Shared, | 451 | }); |
| 452 | }); | 452 | break; |
| 453 | }, | 453 | }, |
| 454 | else => |e| return e, | 454 | // There are no dir components, so you would think that this was |
| | 455 | // unreachable, however we have observed on macOS two processes racing |
| | 456 | // to do openat() with O_CREAT manifest in ENOENT. |
| | 457 | error.FileNotFound => continue, |
| | 458 | else => |e| return e, |
| | 459 | } |
| 455 | } | 460 | } |
| 456 | } | 461 | } |
| 457 | | 462 | |