| author | |
| committer | |
| log | 078aa5f7b20e6e705378713a717bc2dd9afb8835 |
| tree | 29c2dbc7e9072d35837664f799854237a4d76f47 |
| parent | c6cd919a1852e4737fb99aa952eaca8c4d0a51df |
On Linux, locking fails with EAGAIN (vs. EACCES on other systems).
This commit also adds FcntlErrors for EDEADLK and ENOLCK.17 files changed, 150 insertions(+), 73 deletions(-)
lib/std/c/darwin.zig+5-5| ... | @@ -357,11 +357,11 @@ pub const off_t = i64; | ... | @@ -357,11 +357,11 @@ pub const off_t = i64; |
| 357 | pub const ino_t = u64; | 357 | pub const ino_t = u64; |
| 358 | 358 | ||
| 359 | pub const Flock = extern struct { | 359 | pub const Flock = extern struct { |
| 360 | l_start: off_t, | 360 | start: off_t, |
| 361 | l_len: off_t, | 361 | len: off_t, |
| 362 | l_pid: pid_t, | 362 | pid: pid_t, |
| 363 | l_type: i16, | 363 | type: i16, |
| 364 | l_whence: i16, | 364 | whence: i16, |
| 365 | }; | 365 | }; |
| 366 | 366 | ||
| 367 | pub const Stat = extern struct { | 367 | pub const Stat = extern struct { |
lib/std/c/dragonfly.zig+5-5| ... | @@ -929,11 +929,11 @@ pub const LOCK = struct { | ... | @@ -929,11 +929,11 @@ pub const LOCK = struct { |
| 929 | }; | 929 | }; |
| 930 | 930 | ||
| 931 | pub const Flock = extern struct { | 931 | pub const Flock = extern struct { |
| 932 | l_start: off_t, | 932 | start: off_t, |
| 933 | l_len: off_t, | 933 | len: off_t, |
| 934 | l_pid: pid_t, | 934 | pid: pid_t, |
| 935 | l_type: c_short, | 935 | type: c_short, |
| 936 | l_whence: c_short, | 936 | whence: c_short, |
| 937 | }; | 937 | }; |
| 938 | 938 | ||
| 939 | pub const addrinfo = extern struct { | 939 | pub const addrinfo = extern struct { |
lib/std/c/freebsd.zig+6-6| ... | @@ -193,12 +193,12 @@ pub const dl_phdr_info = extern struct { | ... | @@ -193,12 +193,12 @@ pub const dl_phdr_info = extern struct { |
| 193 | }; | 193 | }; |
| 194 | 194 | ||
| 195 | pub const Flock = extern struct { | 195 | pub const Flock = extern struct { |
| 196 | l_start: off_t, | 196 | start: off_t, |
| 197 | l_len: off_t, | 197 | len: off_t, |
| 198 | l_pid: pid_t, | 198 | pid: pid_t, |
| 199 | l_type: i16, | 199 | type: i16, |
| 200 | l_whence: i16, | 200 | whence: i16, |
| 201 | l_sysid: i32, | 201 | sysid: i32, |
| 202 | __unused: [4]u8, | 202 | __unused: [4]u8, |
| 203 | }; | 203 | }; |
| 204 | 204 |
lib/std/c/haiku.zig+5-5| ... | @@ -159,11 +159,11 @@ pub const dl_phdr_info = extern struct { | ... | @@ -159,11 +159,11 @@ pub const dl_phdr_info = extern struct { |
| 159 | }; | 159 | }; |
| 160 | 160 | ||
| 161 | pub const Flock = extern struct { | 161 | pub const Flock = extern struct { |
| 162 | l_type: c_short, | 162 | type: c_short, |
| 163 | l_whence: c_short, | 163 | whence: c_short, |
| 164 | l_start: off_t, | 164 | start: off_t, |
| 165 | l_len: off_t, | 165 | len: off_t, |
| 166 | l_pid: pid_t, | 166 | pid: pid_t, |
| 167 | }; | 167 | }; |
| 168 | 168 | ||
| 169 | pub const msghdr = extern struct { | 169 | pub const msghdr = extern struct { |
lib/std/c/netbsd.zig+5-5| ... | @@ -169,11 +169,11 @@ pub const dl_phdr_info = extern struct { | ... | @@ -169,11 +169,11 @@ pub const dl_phdr_info = extern struct { |
| 169 | }; | 169 | }; |
| 170 | 170 | ||
| 171 | pub const Flock = extern struct { | 171 | pub const Flock = extern struct { |
| 172 | l_start: off_t, | 172 | start: off_t, |
| 173 | l_len: off_t, | 173 | len: off_t, |
| 174 | l_pid: pid_t, | 174 | pid: pid_t, |
| 175 | l_type: i16, | 175 | type: i16, |
| 176 | l_whence: i16, | 176 | whence: i16, |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | pub const addrinfo = extern struct { | 179 | pub const addrinfo = extern struct { |
lib/std/c/openbsd.zig+5-5| ... | @@ -94,11 +94,11 @@ pub const dl_phdr_info = extern struct { | ... | @@ -94,11 +94,11 @@ pub const dl_phdr_info = extern struct { |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | pub const Flock = extern struct { | 96 | pub const Flock = extern struct { |
| 97 | l_start: off_t, | 97 | start: off_t, |
| 98 | l_len: off_t, | 98 | len: off_t, |
| 99 | l_pid: pid_t, | 99 | pid: pid_t, |
| 100 | l_type: c_short, | 100 | type: c_short, |
| 101 | l_whence: c_short, | 101 | whence: c_short, |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | pub const addrinfo = extern struct { | 104 | pub const addrinfo = extern struct { |
lib/std/c/solaris.zig+6-6| ... | @@ -116,13 +116,13 @@ pub const RTLD = struct { | ... | @@ -116,13 +116,13 @@ pub const RTLD = struct { |
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | pub const Flock = extern struct { | 118 | pub const Flock = extern struct { |
| 119 | l_type: c_short, | 119 | type: c_short, |
| 120 | l_whence: c_short, | 120 | whence: c_short, |
| 121 | l_start: off_t, | 121 | start: off_t, |
| 122 | // len == 0 means until end of file. | 122 | // len == 0 means until end of file. |
| 123 | l_len: off_t, | 123 | len: off_t, |
| 124 | l_sysid: c_int, | 124 | sysid: c_int, |
| 125 | l_pid: pid_t, | 125 | pid: pid_t, |
| 126 | __pad: [4]c_long, | 126 | __pad: [4]c_long, |
| 127 | }; | 127 | }; |
| 128 | 128 |
lib/std/fs.zig+8| ... | @@ -1045,6 +1045,8 @@ pub const Dir = struct { | ... | @@ -1045,6 +1045,8 @@ pub const Dir = struct { |
| 1045 | error.FileBusy => unreachable, | 1045 | error.FileBusy => unreachable, |
| 1046 | error.Locked => unreachable, | 1046 | error.Locked => unreachable, |
| 1047 | error.PermissionDenied => unreachable, | 1047 | error.PermissionDenied => unreachable, |
| 1048 | error.DeadLock => unreachable, | ||
| 1049 | error.LockedRegionLimitExceeded => unreachable, | ||
| 1048 | else => |e| return e, | 1050 | else => |e| return e, |
| 1049 | }; | 1051 | }; |
| 1050 | fl_flags &= ~@as(usize, os.O.NONBLOCK); | 1052 | fl_flags &= ~@as(usize, os.O.NONBLOCK); |
| ... | @@ -1052,6 +1054,8 @@ pub const Dir = struct { | ... | @@ -1052,6 +1054,8 @@ pub const Dir = struct { |
| 1052 | error.FileBusy => unreachable, | 1054 | error.FileBusy => unreachable, |
| 1053 | error.Locked => unreachable, | 1055 | error.Locked => unreachable, |
| 1054 | error.PermissionDenied => unreachable, | 1056 | error.PermissionDenied => unreachable, |
| 1057 | error.DeadLock => unreachable, | ||
| 1058 | error.LockedRegionLimitExceeded => unreachable, | ||
| 1055 | else => |e| return e, | 1059 | else => |e| return e, |
| 1056 | }; | 1060 | }; |
| 1057 | } | 1061 | } |
| ... | @@ -1197,6 +1201,8 @@ pub const Dir = struct { | ... | @@ -1197,6 +1201,8 @@ pub const Dir = struct { |
| 1197 | error.FileBusy => unreachable, | 1201 | error.FileBusy => unreachable, |
| 1198 | error.Locked => unreachable, | 1202 | error.Locked => unreachable, |
| 1199 | error.PermissionDenied => unreachable, | 1203 | error.PermissionDenied => unreachable, |
| 1204 | error.DeadLock => unreachable, | ||
| 1205 | error.LockedRegionLimitExceeded => unreachable, | ||
| 1200 | else => |e| return e, | 1206 | else => |e| return e, |
| 1201 | }; | 1207 | }; |
| 1202 | fl_flags &= ~@as(usize, os.O.NONBLOCK); | 1208 | fl_flags &= ~@as(usize, os.O.NONBLOCK); |
| ... | @@ -1204,6 +1210,8 @@ pub const Dir = struct { | ... | @@ -1204,6 +1210,8 @@ pub const Dir = struct { |
| 1204 | error.FileBusy => unreachable, | 1210 | error.FileBusy => unreachable, |
| 1205 | error.Locked => unreachable, | 1211 | error.Locked => unreachable, |
| 1206 | error.PermissionDenied => unreachable, | 1212 | error.PermissionDenied => unreachable, |
| 1213 | error.DeadLock => unreachable, | ||
| 1214 | error.LockedRegionLimitExceeded => unreachable, | ||
| 1207 | else => |e| return e, | 1215 | else => |e| return e, |
| 1208 | }; | 1216 | }; |
| 1209 | } | 1217 | } |
lib/std/os.zig+13-1| ... | @@ -4513,6 +4513,8 @@ pub const FcntlError = error{ | ... | @@ -4513,6 +4513,8 @@ pub const FcntlError = error{ |
| 4513 | FileBusy, | 4513 | FileBusy, |
| 4514 | ProcessFdQuotaExceeded, | 4514 | ProcessFdQuotaExceeded, |
| 4515 | Locked, | 4515 | Locked, |
| 4516 | DeadLock, | ||
| 4517 | LockedRegionLimitExceeded, | ||
| 4516 | } || UnexpectedError; | 4518 | } || UnexpectedError; |
| 4517 | 4519 | ||
| 4518 | pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { | 4520 | pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { |
| ... | @@ -4521,13 +4523,15 @@ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { | ... | @@ -4521,13 +4523,15 @@ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { |
| 4521 | switch (errno(rc)) { | 4523 | switch (errno(rc)) { |
| 4522 | .SUCCESS => return @intCast(usize, rc), | 4524 | .SUCCESS => return @intCast(usize, rc), |
| 4523 | .INTR => continue, | 4525 | .INTR => continue, |
| 4524 | .ACCES => return error.Locked, | 4526 | .AGAIN, .ACCES => return error.Locked, |
| 4525 | .BADF => unreachable, | 4527 | .BADF => unreachable, |
| 4526 | .BUSY => return error.FileBusy, | 4528 | .BUSY => return error.FileBusy, |
| 4527 | .INVAL => unreachable, // invalid parameters | 4529 | .INVAL => unreachable, // invalid parameters |
| 4528 | .PERM => return error.PermissionDenied, | 4530 | .PERM => return error.PermissionDenied, |
| 4529 | .MFILE => return error.ProcessFdQuotaExceeded, | 4531 | .MFILE => return error.ProcessFdQuotaExceeded, |
| 4530 | .NOTDIR => unreachable, // invalid parameter | 4532 | .NOTDIR => unreachable, // invalid parameter |
| 4533 | .DEADLK => return error.DeadLock, | ||
| 4534 | .NOLCK => return error.LockedRegionLimitExceeded, | ||
| 4531 | else => |err| return unexpectedErrno(err), | 4535 | else => |err| return unexpectedErrno(err), |
| 4532 | } | 4536 | } |
| 4533 | } | 4537 | } |
| ... | @@ -4542,6 +4546,8 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { | ... | @@ -4542,6 +4546,8 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { |
| 4542 | error.FileBusy => unreachable, | 4546 | error.FileBusy => unreachable, |
| 4543 | error.Locked => unreachable, | 4547 | error.Locked => unreachable, |
| 4544 | error.PermissionDenied => unreachable, | 4548 | error.PermissionDenied => unreachable, |
| 4549 | error.DeadLock => unreachable, | ||
| 4550 | error.LockedRegionLimitExceeded => unreachable, | ||
| 4545 | else => |e| return e, | 4551 | else => |e| return e, |
| 4546 | }; | 4552 | }; |
| 4547 | fd_flags |= FD_CLOEXEC; | 4553 | fd_flags |= FD_CLOEXEC; |
| ... | @@ -4549,6 +4555,8 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { | ... | @@ -4549,6 +4555,8 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { |
| 4549 | error.FileBusy => unreachable, | 4555 | error.FileBusy => unreachable, |
| 4550 | error.Locked => unreachable, | 4556 | error.Locked => unreachable, |
| 4551 | error.PermissionDenied => unreachable, | 4557 | error.PermissionDenied => unreachable, |
| 4558 | error.DeadLock => unreachable, | ||
| 4559 | error.LockedRegionLimitExceeded => unreachable, | ||
| 4552 | else => |e| return e, | 4560 | else => |e| return e, |
| 4553 | }; | 4561 | }; |
| 4554 | } | 4562 | } |
| ... | @@ -4570,6 +4578,8 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { | ... | @@ -4570,6 +4578,8 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { |
| 4570 | error.FileBusy => unreachable, | 4578 | error.FileBusy => unreachable, |
| 4571 | error.Locked => unreachable, | 4579 | error.Locked => unreachable, |
| 4572 | error.PermissionDenied => unreachable, | 4580 | error.PermissionDenied => unreachable, |
| 4581 | error.DeadLock => unreachable, | ||
| 4582 | error.LockedRegionLimitExceeded => unreachable, | ||
| 4573 | else => |e| return e, | 4583 | else => |e| return e, |
| 4574 | }; | 4584 | }; |
| 4575 | fl_flags |= O.NONBLOCK; | 4585 | fl_flags |= O.NONBLOCK; |
| ... | @@ -4577,6 +4587,8 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { | ... | @@ -4577,6 +4587,8 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { |
| 4577 | error.FileBusy => unreachable, | 4587 | error.FileBusy => unreachable, |
| 4578 | error.Locked => unreachable, | 4588 | error.Locked => unreachable, |
| 4579 | error.PermissionDenied => unreachable, | 4589 | error.PermissionDenied => unreachable, |
| 4590 | error.DeadLock => unreachable, | ||
| 4591 | error.LockedRegionLimitExceeded => unreachable, | ||
| 4580 | else => |e| return e, | 4592 | else => |e| return e, |
| 4581 | }; | 4593 | }; |
| 4582 | } | 4594 | } |
lib/std/os/linux/arm-eabi.zig+5-5| ... | @@ -638,12 +638,12 @@ pub const HWCAP = struct { | ... | @@ -638,12 +638,12 @@ pub const HWCAP = struct { |
| 638 | }; | 638 | }; |
| 639 | 639 | ||
| 640 | pub const Flock = extern struct { | 640 | pub const Flock = extern struct { |
| 641 | l_type: i16, | 641 | type: i16, |
| 642 | l_whence: i16, | 642 | whence: i16, |
| 643 | __pad0: [4]u8, | 643 | __pad0: [4]u8, |
| 644 | l_start: off_t, | 644 | start: off_t, |
| 645 | l_len: off_t, | 645 | len: off_t, |
| 646 | l_pid: pid_t, | 646 | pid: pid_t, |
| 647 | __unused: [4]u8, | 647 | __unused: [4]u8, |
| 648 | }; | 648 | }; |
| 649 | 649 |
lib/std/os/linux/arm64.zig+5-5| ... | @@ -490,11 +490,11 @@ pub const VDSO = struct { | ... | @@ -490,11 +490,11 @@ pub const VDSO = struct { |
| 490 | }; | 490 | }; |
| 491 | 491 | ||
| 492 | pub const Flock = extern struct { | 492 | pub const Flock = extern struct { |
| 493 | l_type: i16, | 493 | type: i16, |
| 494 | l_whence: i16, | 494 | whence: i16, |
| 495 | l_start: off_t, | 495 | start: off_t, |
| 496 | l_len: off_t, | 496 | len: off_t, |
| 497 | l_pid: pid_t, | 497 | pid: pid_t, |
| 498 | __unused: [4]u8, | 498 | __unused: [4]u8, |
| 499 | }; | 499 | }; |
| 500 | 500 |
lib/std/os/linux/mips.zig+5-5| ... | @@ -707,12 +707,12 @@ pub const VDSO = struct { | ... | @@ -707,12 +707,12 @@ pub const VDSO = struct { |
| 707 | }; | 707 | }; |
| 708 | 708 | ||
| 709 | pub const Flock = extern struct { | 709 | pub const Flock = extern struct { |
| 710 | l_type: i16, | 710 | type: i16, |
| 711 | l_whence: i16, | 711 | whence: i16, |
| 712 | __pad0: [4]u8, | 712 | __pad0: [4]u8, |
| 713 | l_start: off_t, | 713 | start: off_t, |
| 714 | l_len: off_t, | 714 | len: off_t, |
| 715 | l_pid: pid_t, | 715 | pid: pid_t, |
| 716 | __unused: [4]u8, | 716 | __unused: [4]u8, |
| 717 | }; | 717 | }; |
| 718 | 718 |
lib/std/os/linux/powerpc.zig+5-5| ... | @@ -643,11 +643,11 @@ pub const VDSO = struct { | ... | @@ -643,11 +643,11 @@ pub const VDSO = struct { |
| 643 | }; | 643 | }; |
| 644 | 644 | ||
| 645 | pub const Flock = extern struct { | 645 | pub const Flock = extern struct { |
| 646 | l_type: i16, | 646 | type: i16, |
| 647 | l_whence: i16, | 647 | whence: i16, |
| 648 | l_start: off_t, | 648 | start: off_t, |
| 649 | l_len: off_t, | 649 | len: off_t, |
| 650 | l_pid: pid_t, | 650 | pid: pid_t, |
| 651 | }; | 651 | }; |
| 652 | 652 | ||
| 653 | pub const msghdr = extern struct { | 653 | pub const msghdr = extern struct { |
lib/std/os/linux/powerpc64.zig+5-5| ... | @@ -617,11 +617,11 @@ pub const VDSO = struct { | ... | @@ -617,11 +617,11 @@ pub const VDSO = struct { |
| 617 | }; | 617 | }; |
| 618 | 618 | ||
| 619 | pub const Flock = extern struct { | 619 | pub const Flock = extern struct { |
| 620 | l_type: i16, | 620 | type: i16, |
| 621 | l_whence: i16, | 621 | whence: i16, |
| 622 | l_start: off_t, | 622 | start: off_t, |
| 623 | l_len: off_t, | 623 | len: off_t, |
| 624 | l_pid: pid_t, | 624 | pid: pid_t, |
| 625 | __unused: [4]u8, | 625 | __unused: [4]u8, |
| 626 | }; | 626 | }; |
| 627 | 627 |
lib/std/os/linux/riscv64.zig+5-5| ... | @@ -480,11 +480,11 @@ pub const timeval = extern struct { | ... | @@ -480,11 +480,11 @@ pub const timeval = extern struct { |
| 480 | }; | 480 | }; |
| 481 | 481 | ||
| 482 | pub const Flock = extern struct { | 482 | pub const Flock = extern struct { |
| 483 | l_type: i16, | 483 | type: i16, |
| 484 | l_whence: i16, | 484 | whence: i16, |
| 485 | l_start: off_t, | 485 | start: off_t, |
| 486 | l_len: off_t, | 486 | len: off_t, |
| 487 | l_pid: pid_t, | 487 | pid: pid_t, |
| 488 | __unused: [4]u8, | 488 | __unused: [4]u8, |
| 489 | }; | 489 | }; |
| 490 | 490 |
lib/std/os/linux/sparc64.zig+5-5| ... | @@ -648,11 +648,11 @@ pub const VDSO = struct { | ... | @@ -648,11 +648,11 @@ pub const VDSO = struct { |
| 648 | }; | 648 | }; |
| 649 | 649 | ||
| 650 | pub const Flock = extern struct { | 650 | pub const Flock = extern struct { |
| 651 | l_type: i16, | 651 | type: i16, |
| 652 | l_whence: i16, | 652 | whence: i16, |
| 653 | l_start: off_t, | 653 | start: off_t, |
| 654 | l_len: off_t, | 654 | len: off_t, |
| 655 | l_pid: pid_t, | 655 | pid: pid_t, |
| 656 | }; | 656 | }; |
| 657 | 657 | ||
| 658 | pub const msghdr = extern struct { | 658 | pub const msghdr = extern struct { |
lib/std/os/test.zig+57| ... | @@ -821,3 +821,60 @@ test "writev longer than IOV_MAX" { | ... | @@ -821,3 +821,60 @@ test "writev longer than IOV_MAX" { |
| 821 | const amt = try file.writev(&iovecs); | 821 | const amt = try file.writev(&iovecs); |
| 822 | try testing.expectEqual(@as(usize, os.IOV_MAX), amt); | 822 | try testing.expectEqual(@as(usize, os.IOV_MAX), amt); |
| 823 | } | 823 | } |
| 824 | |||
| 825 | test "POSIX file locking with fcntl" { | ||
| 826 | if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; | ||
| 827 | |||
| 828 | var tmp = std.testing.tmpDir(.{}); | ||
| 829 | defer tmp.cleanup(); | ||
| 830 | |||
| 831 | // Create a temporary lock file | ||
| 832 | var file = try tmp.dir.createFile("lock", .{ .read = true }); | ||
| 833 | defer file.close(); | ||
| 834 | try file.setEndPos(2); | ||
| 835 | const fd = file.handle; | ||
| 836 | |||
| 837 | // Place an exclusive lock on the first byte, and a shared lock on the second byte: | ||
| 838 | var struct_flock = std.mem.zeroInit(std.os.Flock, .{ .type = std.os.F.WRLCK }); | ||
| 839 | _ = try std.os.fcntl(fd, std.os.F.SETLK, @ptrToInt(&struct_flock)); | ||
| 840 | struct_flock.start = 1; | ||
| 841 | struct_flock.type = std.os.F.RDLCK; | ||
| 842 | _ = try std.os.fcntl(fd, std.os.F.SETLK, @ptrToInt(&struct_flock)); | ||
| 843 | |||
| 844 | // Check the locks in a child process: | ||
| 845 | const pid = try std.os.fork(); | ||
| 846 | if (pid == 0) { | ||
| 847 | // child expects be denied the exclusive lock: | ||
| 848 | struct_flock.start = 0; | ||
| 849 | struct_flock.type = std.os.F.WRLCK; | ||
| 850 | try expectError(error.Locked, std.os.fcntl(fd, std.os.F.SETLK, @ptrToInt(&struct_flock))); | ||
| 851 | // child expects to get the shared lock: | ||
| 852 | struct_flock.start = 1; | ||
| 853 | struct_flock.type = std.os.F.RDLCK; | ||
| 854 | _ = try std.os.fcntl(fd, std.os.F.SETLK, @ptrToInt(&struct_flock)); | ||
| 855 | // child waits for the exclusive lock in order to test deadlock: | ||
| 856 | struct_flock.start = 0; | ||
| 857 | struct_flock.type = std.os.F.WRLCK; | ||
| 858 | _ = try std.os.fcntl(fd, std.os.F.SETLKW, @ptrToInt(&struct_flock)); | ||
| 859 | // child exits without continuing: | ||
| 860 | std.os.exit(0); | ||
| 861 | } else { | ||
| 862 | // parent waits for child to get shared lock: | ||
| 863 | std.time.sleep(1 * std.time.ns_per_ms); | ||
| 864 | // parent expects deadlock when attempting to upgrade the shared lock to exclusive: | ||
| 865 | struct_flock.start = 1; | ||
| 866 | struct_flock.type = std.os.F.WRLCK; | ||
| 867 | try expectError(error.DeadLock, std.os.fcntl(fd, std.os.F.SETLKW, @ptrToInt(&struct_flock))); | ||
| 868 | // parent releases exclusive lock: | ||
| 869 | struct_flock.start = 0; | ||
| 870 | struct_flock.type = std.os.F.UNLCK; | ||
| 871 | _ = try std.os.fcntl(fd, std.os.F.SETLK, @ptrToInt(&struct_flock)); | ||
| 872 | // parent releases shared lock: | ||
| 873 | struct_flock.start = 1; | ||
| 874 | struct_flock.type = std.os.F.UNLCK; | ||
| 875 | _ = try std.os.fcntl(fd, std.os.F.SETLK, @ptrToInt(&struct_flock)); | ||
| 876 | // parent waits for child: | ||
| 877 | const result = std.os.waitpid(pid, 0); | ||
| 878 | try expect(result.status == 0 * 256); | ||
| 879 | } | ||
| 880 | } |