diff --git a/src/bin/main.ml b/src/bin/main.ml index 3675612..b5e00dc 100644 --- a/src/bin/main.ml +++ b/src/bin/main.ml @@ -41,14 +41,13 @@ let sh ~name:_ shell env = let interactive = shell.arguments = [] in let pos_zero = match shell.arguments with f :: _ -> f | [] -> "msh" in Eio.Switch.run ~name:"async" @@ fun async_switch -> - let signal_handler f = Eio_posix.run @@ fun _ -> f () in let ctx argv = C.make_ctx ~interactive (Merry_posix.State.make ~home:(Sys.getenv "HOME" ^ "/") (Fpath.v (Merry.Eunix.cwd ()))) executor ~fs:env#fs ~stdin:env#stdin ~stdout:env#stdout ~async_switch - ~options:shell.options ~argv ~program:pos_zero ~signal_handler + ~options:shell.options ~argv ~program:pos_zero in match (shell.arguments, shell.command) with | [], false -> diff --git a/src/lib/eval.ml b/src/lib/eval.ml index e7ac09a..4f50db9 100644 --- a/src/lib/eval.ml +++ b/src/lib/eval.ml @@ -80,7 +80,10 @@ module Make (S : Types.State) (E : Types.Exec) = struct module J = Job.Make (E) module A = Arith.Make (S) - type signal_handler = { run : (unit -> unit) -> unit; sigint_set : bool } + type signal_handler = { + run_queue : (ctx -> ctx Exit.t) Queue.t; + sigint_set : bool; + } and ctx = { interactive : bool; @@ -184,9 +187,9 @@ module Make (S : Types.State) (E : Types.Exec) = struct ?(background_jobs = []) ?(last_background_process = "") ?current_pipeline ?last_pipeline_status ?(functions = []) ?exit_handler ?(options = Built_ins.Options.default) ?(hash = Hash.empty) - ?(umask = 0o22) ~fs ~stdin ~stdout ~async_switch ~program ~argv - ~signal_handler state executor = - let signal_handler = { run = signal_handler; sigint_set = false } in + ?(umask = 0o22) ~fs ~stdin ~stdout ~async_switch ~program ~argv state + executor = + let signal_handler = { run_queue = Queue.create (); sigint_set = false } in let state = S.update state ~param:"IFS" [ Ast.Fragment.make " \t\n" ] |> Result.get_ok |> fun s -> @@ -2070,10 +2073,12 @@ module Make (S : Types.State) (E : Types.Exec) = struct match action with | Action m -> let ast = Ast.of_string m in - let f _ = - saved_ctx.signal_handler.run @@ fun () -> - let _, _ = run (Exit.zero ctx) ast in - () + let f _signal_number = + Queue.push + (fun ctx -> + let ctx, _ = run (Exit.zero ctx) ast in + ctx) + saved_ctx.signal_handler.run_queue in Sys.Signal_handle f | Default -> Sys.Signal_default @@ -2241,23 +2246,29 @@ module Make (S : Types.State) (E : Types.Exec) = struct (* Handled separately *) assert false + and poll_signals ctx = + let rec loop ctx = + match Queue.pop ctx.signal_handler.run_queue with + | f -> loop (Exit.value (f ctx)) + | exception Queue.Empty -> ctx + in + loop ctx + and exec (initial_ctx : ctx) ((command, sep) : Ast.complete_command) = let rec loop : ?async:bool -> Eio.Switch.t -> ctx -> Ast.clist -> ctx Exit.t = - fun ?(async = false) sw ctx -> function - | Nlist.Singleton (c, sep) -> - let async = - match sep with Semicolon -> async | Ampersand -> true - in - handle_and_or ~sw ~async ctx c - | Nlist.Cons ((c, sep), cs) -> ( - let async = - match sep with Semicolon -> async | Ampersand -> true - in - match handle_and_or ~sw ~async ctx c with - | Exit.Zero ctx -> loop sw ctx cs - | Exit.Nonzero { value = ctx; _ } as v -> - if should_exit v then v else loop sw ctx cs) + fun ?(async = false) sw ctx v -> + let ctx = poll_signals ctx in + match v with + | Nlist.Singleton (c, sep) -> + let async = match sep with Semicolon -> async | Ampersand -> true in + handle_and_or ~sw ~async ctx c + | Nlist.Cons ((c, sep), cs) -> ( + let async = match sep with Semicolon -> async | Ampersand -> true in + match handle_and_or ~sw ~async ctx c with + | Exit.Zero ctx -> loop sw ctx cs + | Exit.Nonzero { value = ctx; _ } as v -> + if should_exit v then v else loop sw ctx cs) in match sep with | Some Semicolon | None -> diff --git a/src/lib/eval.mli b/src/lib/eval.mli index c8e8ab8..d3b7e14 100644 --- a/src/lib/eval.mli +++ b/src/lib/eval.mli @@ -28,7 +28,6 @@ module Make (S : Types.State) (E : Types.Exec) : sig async_switch:Switch.t -> program:string -> argv:string array -> - signal_handler:((unit -> unit) -> unit) -> S.t -> E.t -> ctx diff --git a/test/wordexp.ml b/test/wordexp.ml index bbef18d..26f1c50 100644 --- a/test/wordexp.ml +++ b/test/wordexp.ml @@ -16,7 +16,6 @@ let with_default_ctx ?(args = []) ?(params = []) ?(home = "/home/merry/") env fn let interactive = false in let pos_zero = "msh" in Eio.Switch.run @@ fun async_switch -> - let signal_handler f = Eio_posix.run @@ fun _ -> f () in let state = Merry_posix.State.make ~home (Fpath.v (Merry.Eunix.cwd ())) in let state = List.fold_left @@ -28,7 +27,7 @@ let with_default_ctx ?(args = []) ?(params = []) ?(home = "/home/merry/") env fn let ctx = C.make_ctx ~interactive state executor ~fs:env#fs ~stdin:env#stdin ~stdout:env#stdout ~async_switch ~argv:(Array.of_list args) - ~program:pos_zero ~signal_handler + ~program:pos_zero in fn ctx