Skip to content

Commit 917e022

Browse files
committed
fixup! Windows safe kill.
1 parent 37a8edf commit 917e022

2 files changed

Lines changed: 15 additions & 36 deletions

File tree

lib/olly_common/launch.ml

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
external is_process_alive : int -> bool = "olly_is_process_alive"
2-
3-
(* On Windows, Unix.create_process_env returns a process HANDLE, not a PID.
4-
This C stub calls GetProcessId(handle) on Windows to get the real PID.
5-
On Unix it's the identity function since the handle IS the PID. *)
62
external get_process_id : int -> int = "olly_get_process_id"
73

84
let lost_events ring_id num =
@@ -13,19 +9,21 @@ type subprocess = {
139
cursor : Runtime_events.cursor;
1410
close : unit -> unit;
1511
pid : int;
16-
(* Terminate the process and wait for it to fully exit. Safe to call
17-
more than once and safe to call after natural exit. *)
18-
kill : unit -> unit;
1912
}
2013

14+
2115
type runtime_events_config = { log_wsize : int option; dir : string option }
2216
type exec_config = Attach of string * int | Execute of string list
2317

2418
(* Raised by exec_process to indicate various unrecoverable failures. *)
2519
exception Fail of string
2620

21+
(* Function to kill a spawned process. Only the spawner can terminate
22+
the child. *)
23+
type kill = unit -> unit
24+
2725
let exec_process (config : runtime_events_config) (args : string list) :
28-
subprocess =
26+
subprocess * kill =
2927
if not (List.length args > 0) then
3028
raise (Fail (Printf.sprintf "no executable provided for exec_process"));
3129

@@ -88,7 +86,7 @@ let exec_process (config : runtime_events_config) (args : string list) :
8886
in
8987
let child_pid = get_process_id child_handle in
9088
(* OCaml's Unix module on Windows uses the value returned by
91-
create_process (a HANDLE) as its process identifier both Unix.kill
89+
create_process (a HANDLE) as its process identifier, both Unix.kill
9290
and Unix.waitpid expect that value, NOT the real OS PID from
9391
GetProcessId. On Unix the handle and PID coincide.
9492
@@ -160,7 +158,7 @@ let exec_process (config : runtime_events_config) (args : string list) :
160158
try Unix.unlink ring_file with Unix.Unix_error _ -> ()
161159
end
162160
in
163-
{ alive; cursor; close; pid = child_pid; kill }
161+
({ alive; cursor; close; pid = child_pid }, kill)
164162

165163
let attach_process (dir : string) (pid : int) : subprocess =
166164
(* Check the target process exists before attempting to attach *)
@@ -187,25 +185,11 @@ let attach_process (dir : string) (pid : int) : subprocess =
187185
in
188186
let alive () = is_process_alive pid
189187
and close () = Runtime_events.free_cursor cursor in
190-
(* Best-effort: we did not create the process, so we have no handle.
191-
On Unix this kills via SIGKILL. On Windows this is effectively a
192-
no-op because OCaml's Unix.kill expects the value returned by
193-
create_process (a HANDLE), not an arbitrary PID — terminating an
194-
attached-to process there would need a Win32 OpenProcess +
195-
TerminateProcess C stub. *)
196-
let kill () =
197-
(try Unix.kill pid Sys.sigkill
198-
with Unix.Unix_error _ | Invalid_argument _ -> ());
199-
let deadline = Unix.gettimeofday () +. 2.0 in
200-
while is_process_alive pid && Unix.gettimeofday () < deadline do
201-
Unix.sleepf 0.02
202-
done
203-
in
204-
{ alive; cursor; close; pid; kill }
188+
{ alive; cursor; close; pid }
205189

206190
let launch_process config (exec_args : exec_config) : subprocess =
207191
match exec_args with
208-
| Execute argsl -> exec_process config argsl
192+
| Execute argsl -> fst (exec_process config argsl)
209193
| Attach (dir, pid) -> attach_process dir pid
210194

211195
let interrupted = Atomic.make false

test/test_launch.ml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,17 @@ let process_launch () =
2727
Alcotest.(check bool)
2828
"process should launch" true
2929
(try
30-
let a = Launch.exec_process config [ "./run_endlessly.exe" ] in
31-
(* Check the child is alive using waitpid WNOHANG.
32-
Unix.kill with signal 0 is not supported on Windows. *)
30+
let a, kill = Launch.exec_process config [ "./run_endlessly.exe" ] in
3331
let launched = a.alive () in
3432
(* Clean up the child process so it doesn't leak.
3533
On Windows, open files cannot be deleted, so the orphan process
3634
would prevent dune from cleaning up its temp directory. *)
37-
a.kill ();
35+
kill ();
3836
a.close ();
3937
launched
40-
with
41-
(* Any exceptions indicate a failure to launch *)
42-
| Unix.Unix_error (Unix.ENOENT, _, _) -> false
43-
| _exn ->
44-
Printf.printf "%s" (Printexc.to_string _exn);
45-
false)
38+
with _exn ->
39+
Printf.eprintf "%s" (Printexc.to_string _exn);
40+
false)
4641

4742
let () =
4843
let open Alcotest in

0 commit comments

Comments
 (0)