6
6
(** Calls external programs, creates pipelines, etc. (full interface) *)
8
(** This module is {b not thread-safe} because of undefined behaviour
9
* of some signal related functions in multi-threaded programs. This
10
* problem cannot be easily fixed, as the necessary multi-threading
11
* primitives are not available in O'Caml. (Maybe there is a solution
12
* for bytecode threads...)
14
* Nevertheless, [shell] often seems to work in a multi-threaded environment.
15
* However, strange things can happen when two threads start new processes
16
* at the same time, because they overwrite the global signal mask. As
17
* a minimum precaution you should ensure that only one thread uses [shell]
18
* at any time. Anyway, you have been warned.
8
(** This module is now thread-safe (as of May 2009), provided the
9
threads do no share the same [Shell] or [Shell_sys] values.
10
Problems reported earlier here have been resolved.
13
(** If you get errors like "Netsys_posix.watch_subprocess: uninitialized"
14
you should call {!Shell_sys.install_job_handlers}.
22
17
(** {1 Common exceptions} *)
24
19
exception Fatal_error of exn
257
266
(** Returns the process ID of the process *)
259
268
val status : process -> Unix.process_status
260
(** Reports the status as determined by [wait] (below): If the process
269
(** Reports the status so far known: If the process
261
270
* has terminated, the status of the process is returned.
262
271
* If the process is still running, [Not_found] will be raised.
264
* Note: This function does {b not} call [Unix.waitpid] to get the status
265
* and to release the process ID. This is done by [wait] below.
268
274
val command_of_process : process -> command
269
275
(** Returns the command that is now running as the process *)
272
File_read of Unix.file_descr (** Data can be read from the fd *)
273
| File_write of Unix.file_descr (** Data can be written to the fd *)
274
| File_except of Unix.file_descr (** OOB data can be read from the fd *)
275
| Process_event of process (** The process has changed its status *)
276
| Signal (** A signal happened *)
277
(** Events used by [wait] *)
280
?wnohang:bool -> (* default: false *)
281
?wuntraced:bool -> (* default: false *)
282
?restart:bool -> (* default: false *)
283
?check_interval:float -> (* default: 0.1 *)
284
?read:(Unix.file_descr list) -> (* default: [] *)
285
?write:(Unix.file_descr list) -> (* default: [] *)
286
?except:(Unix.file_descr list) -> (* default: [] *)
289
(** Watches the given list of processes and the file descriptors [read],
290
* [write], and [except], and waits until events for these resources
291
* have happened, and reports these. It is allowed that the list of
292
* processes includes stopped and terminated processes.
294
* The function returns immediately with [] if it is no longer possible
295
* that any event can happen.
297
* The passed file descriptors must be open.
299
* The function reports events under these conditions:
300
* - A process of the list terminates, either regularly, or because of
301
* a signal. This is recorded as [Process_event].
302
* - A process of the list stops, and [wuntraced = true]. This is also
303
* recorded as [Process_event].
304
* - A file descriptor of the [read] list delivers data. This is a
306
* - A file descriptor of the [write] list accepts data. This is a
307
* [File_write] event.
308
* - A file descriptor of the [except] list delivers data. This is a
309
* [File_except] event.
312
* - The list of processes may contain terminated processes (that no longer
313
* exist) as long as the process status has already been recorded by a
314
* previous [wait] invocation.
315
* - If [wait] does not restart automatically on a signal, the function
316
* will raise [Unix.Unix_error(Unix.EINTR,_,_)] when the signal condition
318
* - If a process causes both process and descriptor events at the same time,
319
* it is not specified which events are reported first.
320
* - Only every [check_interval] seconds it is checked whether there are
321
* process events. File descriptor events are reported without delay.
323
* It is suggested to install a signal handler for SIGCHLD to improve
324
* the responsiveness for process events. It is sufficient to install
325
* an empty handler for this effect.
327
* @param wnohang If [true], it is immediately checked whether file or
328
* process events have happend, and if so, the event list is returned.
329
* When there are no events to report, the empty list is immediately
330
* returned. Default: [false]
331
* @param wuntraced Whether to report events about stopped processes.
333
* @param restart Whether to restart the event loop when a signal
334
* interrupts the loop. If [true], Unix errors of the type EINTR
335
* cannot happen any longer. Default: [false]
336
* @param check_interval How frequently the processes are checked for
337
* events (in seconds). In addition to this, the processes are also
338
* checked when a signal happens. Default: 0.1
339
* @param read The file descriptors to check for read events
340
* @param write The file descriptors to check for write events
341
* @param except The file descriptors to check for out-of-band events
344
277
val call : command -> process
345
278
(** Executes the command and waits until the process terminates
346
279
* (synchronous execution a la [system], but no intermediate shell).
360
293
(* ******************************************************************** *)
361
(* ** system event handler type ** *)
362
(* ******************************************************************** *)
364
(** {1 Foreign event loops} *)
366
(** The type [system_handler] can be used to watch the progress of
367
* jobs from a foreign event loop instead of [wait]. This interface
368
* is needed for the integration into the Unixqueue framework.
371
type system_handler =
373
?wuntraced:bool -> (* default: false *)
374
?check_interval:float -> (* default: 0.1 *)
375
?read:(Unix.file_descr list) -> (* default: [] *)
376
?write:(Unix.file_descr list) -> (* default: [] *)
377
?except:(Unix.file_descr list) -> (* default: [] *)
379
(process_event list -> unit) -> (* callback for events *)
380
unit; (** Register an event handler *)
383
unit -> unit; (** Start the event loop *)
385
(** There are two record components:
387
* [sys_register]: By calling this function a callback function for the
388
* specified events is registered. The meaning of the arguments is the
389
* same as for [wait], except of the last argument which is the callback
390
* function of type [process_event list -> unit]. Instead of returning
391
* the events like [wait], [sys_register] calls this function back
392
* to deliver the events.
394
* [sys_wait]: By calling this function the event loop is started, and
395
* events are delivered to the registered callback. If exceptions are
396
* raised in the callback function these will not be caught, so the
397
* caller of [sys_wait] will get them. It must be possible to restart
398
* [sys_wait] in this case.
400
* The callback function can change the list of interesting events by
401
* calling [sys_register] again.
403
* If effectively no events are interesting ([sys_register] is called without
404
* file descriptors and no running process) the callback function is called
405
* with an empty [process_event list] once. If it does not register a new
406
* callback, the event loop will stop, and [sys_wait] will return normally.
410
(* ******************************************************************** *)
412
295
(* ******************************************************************** *)
647
530
* happened, the function sets [job_status] to [Job_running].
654
(** Registers the job at the passed [system_handler]. This is not necessary
655
* if you directly call [finish_job].
533
(** This type of engine also returns the [job] and the [job_instance].
535
class type ['t] job_handler_engine_type = object
536
inherit ['t] Uq_engines.engine
539
(** Returns the called job *)
541
method job_instance : job_instance
542
(** Returns the job instance *)
546
class job_engine : Unixqueue.event_system -> job_instance ->
547
[unit] job_handler_engine_type
548
(** The [job_engine] watches the job, and looks whether the processes
549
are finished, and if so, it records the process statuses. Also,
550
the engine takes care of pumping producer data into the job,
551
and of collecting consumer data.
660
?sys:system_handler ->
661
555
job_instance -> unit
662
(** Waits until all of the processes of the job have terminated.
663
* The function handles all producer/consumer events and calls the
664
* producer/consumer functions as necessary.
666
* Exceptions raised by the producer/consumer functions are not caught.
667
* In this case, [finish_job] is restartable.
669
* The [sys] argument determines the system_handler ([standard_system_handler]
670
* by default). The job instance is registered at the system handler,
671
* and it is waited until the job finishes. Roughly, [finish_job]
674
* register_job sys jobinst;
556
(** This creates a [job_engine] internally and runs until it is
557
* finished, i.e. until the job has been executed.
559
* In previous version of Ocamlnet there was an optional [sys]
560
* argument. This is gone now. Also, the error handling is different.
561
* It is no longer possible to restart [finish_job] when an error
822
692
* - The keyboard signals SIGINT and SIGQUIT are forwarded to all jobs
823
693
* which are running in the background (and thus are not
824
694
* automatically notified) and want to get such signals ([forward_signals]).
825
* After the signals have been forwarded, the previous signal action
827
695
* - The signals SIGTERM and SIGHUP are (if the handler is installed)
828
696
* forwarded to all dependent processes (regardless whether they are
829
697
* running in their own Unix process group or not, and regardless of
830
698
* [forward_signals]).
831
* After the signals have been forwarded, the previous signal action
833
699
* - The [at_exit] handler sends a SIGTERM to all dependent processes, too.
834
* - the SIGCHLD handler calls [watch_for_zombies].
835
* After this function is called, the previous signal action
836
* is performed; however if the previous action was [Signal_ignore]
837
* this is incorrectly interpreted as empty action (zombies are not
839
* - The handler for SIGPIPE does nothing; note that a previous action
840
* is overwritten (the parameter is called [set_sigpipe] to stress this)
842
* Dependent processes are:
843
* - For jobs with mode = [Foreground] or [Background]: the processes
844
* of the corresponding Unix process group
845
* - For jobs with mode = [Same_as_caller]: the actually started
701
* In previous versions of Ocamlnet it was also possible to configure
702
* [catch_sigchld] to set whether a SIGCHLD handler is installed. This
703
* is now always done.
705
* In previous versions of Ocamlnet there was also a [set_sigpipe] flag.
706
* This flag is gone as a SIGPIPE handler is now always installed.
708
* The handlers are now managed by {!Netsys_signal}. The handlers of this
709
* module set the [keep_default] flag for SIGINT, SIGQUIT, SIGTERM, and
710
* SIGHUP, so that the default action for these signals is executed after
711
* the forwarding to the child processes is done. By setting another
712
* handler in {!Netsys_signal} without that flag this behavior can be
848
715
* Note that if an uncaught exception leads to program termination,
849
716
* this situation will not be detected; any running jobs will
853
720
* [install_job_handlers] (below) is invoked.
854
721
* The function fails if the handlers are already installed.
856
* KNOWN BUGS: At least for O'Caml 3.00, the handlers do not call the old
857
* signal handlers after their own work has been done; this is due to an
858
* error in Sys.signal.
723
* Win32: No handlers are installed. It would be desirable to some extent
724
* that at least [at_exit] is honoured, however, this is not yet done.
860
726
* @param catch_sigint whether to install a SIGINT handler (default: [true])
861
727
* @param catch_sigquit whether to install a SIGQUIT handler (default: [true])
862
728
* @param catch_sigterm whether to install a SIGTERM handler (default: [true])
863
729
* @param catch_sighup whether to install a SIGHUP handler (default: [true])
864
* @param catch_sigchld whether to install a SIGCHLD handler (default: [true])
865
* @param set_sigpipe whether to set a SIGPIPE handler (default: [true])
866
730
* @param at_exit whether to set the [at_exit] handler (default: [true])
878
742
* Unixqueue now, which is much more powerful.
884
val init_mt : (unit -> ((unit -> unit) * (unit -> unit))) -> unit
745
(** Also no longer supported because the type [system_handler] is gone:
747
{[type system_handler]}
749
{[ type process_event ]}
752
?wnohang:bool -> (* default: false *)
753
?wuntraced:bool -> (* default: false *)
754
?restart:bool -> (* default: false *)
755
?check_interval:float -> (* default: 0.1 *)
756
?read:(Unix.file_descr list) -> (* default: [] *)
757
?write:(Unix.file_descr list) -> (* default: [] *)
758
?except:(Unix.file_descr list) -> (* default: [] *)
762
{[val register_job : system_handler -> job_instance -> unit]}
764
{[val iter_job_instances : f:(job_instance -> unit) -> unit]}
766
{[val watch_for_zombies : unit -> unit]}
768
{[val process_group_expects_signals : job_instance -> bool]}
775
val enable : bool ref
776
(** Enables {!Netlog}-style debugging of this module *)