Skip to content

Commit 9608c65

Browse files
committed
fix(stdune): preserve Windows flock handles and errors
Handle_val dereferences an OCaml custom block and must not be evaluated after releasing the runtime. Reacquiring the runtime can also overwrite the thread-local Windows last-error value from LockFileEx or UnlockFileEx. Extract each handle while holding the runtime and save GetLastError immediately after a failed system call. Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
1 parent 6830a0d commit 9608c65

1 file changed

Lines changed: 14 additions & 4 deletions

File tree

otherlibs/stdune/src/dune_flock.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
CAMLprim value dune_flock_lock(value v_fd, value v_block, value v_exclusive) {
1111
CAMLparam3(v_fd, v_block, v_exclusive);
1212
OVERLAPPED overlapped = { 0 };
13+
HANDLE fd = FD_val(v_fd);
14+
DWORD error = ERROR_SUCCESS;
1315
DWORD ok, dwFlags = 0;
1416
if (Bool_val(v_exclusive)) {
1517
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
@@ -18,10 +20,13 @@ CAMLprim value dune_flock_lock(value v_fd, value v_block, value v_exclusive) {
1820
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
1921
}
2022
caml_release_runtime_system();
21-
ok = LockFileEx(FD_val(v_fd), dwFlags, 0, MAXDWORD, MAXDWORD, &overlapped);
23+
ok = LockFileEx(fd, dwFlags, 0, MAXDWORD, MAXDWORD, &overlapped);
24+
if (!ok) {
25+
error = GetLastError();
26+
}
2227
caml_acquire_runtime_system();
2328
if (!ok) {
24-
win32_maperr(GetLastError());
29+
win32_maperr(error);
2530
uerror("LockFileEx", Nothing);
2631
}
2732
CAMLreturn(Val_unit);
@@ -30,12 +35,17 @@ CAMLprim value dune_flock_lock(value v_fd, value v_block, value v_exclusive) {
3035
CAMLprim value dune_flock_unlock(value v_fd) {
3136
CAMLparam1(v_fd);
3237
OVERLAPPED overlapped = { 0 };
38+
HANDLE fd = FD_val(v_fd);
39+
DWORD error = ERROR_SUCCESS;
3340
DWORD ok;
3441
caml_release_runtime_system();
35-
ok = UnlockFileEx(FD_val(v_fd), 0, MAXDWORD, MAXDWORD, &overlapped);
42+
ok = UnlockFileEx(fd, 0, MAXDWORD, MAXDWORD, &overlapped);
43+
if (!ok) {
44+
error = GetLastError();
45+
}
3646
caml_acquire_runtime_system();
3747
if (!ok) {
38-
win32_maperr(GetLastError());
48+
win32_maperr(error);
3949
uerror("UnlockFileEx", Nothing);
4050
}
4151
CAMLreturn(Val_unit);

0 commit comments

Comments
 (0)