~ubuntu-branches/ubuntu/trusty/ocamlnet/trusty

« back to all changes in this revision

Viewing changes to src/shell/shell_sys.mli

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu
  • Date: 2011-09-02 14:12:33 UTC
  • mfrom: (18.2.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110902141233-zbj0ygxb92u6gy4z
Tags: 3.4-1
* New upstream release
  - add a new NetcgiRequire directive to ease dependency management
    (Closes: #637147)
  - remove patches that were applied upstream:
    + Added-missing-shebang-lines-in-example-shell-scripts
    + Try-also-ocamlc-for-POSIX-threads

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
(** Calls external programs, creates pipelines, etc. (full interface) *)
7
7
 
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...)
13
 
 *
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.
 
11
*)
 
12
 
 
13
(** If you get errors like "Netsys_posix.watch_subprocess: uninitialized"
 
14
    you should call {!Shell_sys.install_job_handlers}.
19
15
 *)
20
16
 
21
 
 
22
17
(** {1 Common exceptions} *)
23
18
 
24
19
exception Fatal_error of exn
146
141
   *
147
142
   * @param path The search path. By default, the contents of the
148
143
   *   variable PATH of the current environment, split by ':', are
149
 
   *   used
 
144
   *   used (Win32: SearchPath is used)
150
145
   *)
151
146
 
152
147
val get_cmdname     : command -> string
215
210
  | Current_group     (** Started process remains in the current group *)
216
211
  (** Determines in which process group the new process will run *)
217
212
 
 
213
type fwd_mode =
 
214
    No_forward          (** No forwarding of keyboard signals *)
 
215
  | Forward_to_process  (** Forward signals directly to subprocess *)
 
216
  | Forward_to_group    (** Forward signals to the process group of the subprocess *)
 
217
  (** Determines whether and how keyboard signals (SIGINT, SIGQUIT) are
 
218
      forwarded from the caller to the new child. There is no forwarding
 
219
      in Win32 - all console applications get the keyboard signals anyway.
 
220
   *)
 
221
 
 
222
 
218
223
val run :
219
224
      ?group:group_action ->       (* default: Current_group *)
 
225
      ?forward_mode:fwd_mode ->    (* default: No_forward *)
220
226
      ?pipe_assignments:((Unix.file_descr * Unix.file_descr) list) ->
221
227
                                   (* default: [] *)
222
228
      command ->
241
247
   *
242
248
   * @param group Determines in which process group the new process will
243
249
   *   run. By default [Current_group].
 
250
   * @param forward_mode Whether and how to forward keyboard signals
 
251
   *   to the new child. By default [No_forward]. The Win32 implementation
 
252
   *   ignores this argument.
244
253
   * @param pipe_assignments A list of descriptor pairs [(fd_from,fd_to)].
245
254
   *   The descriptor [fd_from] in the current process will be assigned
246
255
   *   to [fd_to] in the started subprocess. In order to
257
266
  (** Returns the process ID of the process *)
258
267
 
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.
263
 
   *
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.
266
272
   *)
267
273
 
268
274
val command_of_process : process -> command
269
275
  (** Returns the command that is now running as the process *)
270
276
 
271
 
type process_event =
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] *)
278
 
 
279
 
val 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: [] *)
287
 
      process list ->
288
 
        process_event list
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.
293
 
 *
294
 
 * The function returns immediately with [] if it is no longer possible
295
 
 * that any event can happen.
296
 
 *
297
 
 * The passed file descriptors must be open.
298
 
 *
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
305
 
 *   [File_read] event.
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.
310
 
 *
311
 
 * Notes:
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
317
 
 *   is caught.
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.
322
 
 *
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.
326
 
 *
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.
332
 
 *   Default: [false]
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
342
 
 *)
343
 
 
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).
358
291
 
359
292
 
360
293
(* ******************************************************************** *)
361
 
(* **                 system event handler type                      ** *)
362
 
(* ******************************************************************** *)
363
 
 
364
 
(** {1 Foreign event loops} *)
365
 
 
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.
369
 
 *)
370
 
 
371
 
type system_handler =
372
 
    { sys_register :
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: [] *)
378
 
        process list ->
379
 
        (process_event list -> unit) ->   (* callback for events *)
380
 
          unit;        (** Register an event handler *)
381
 
 
382
 
      sys_wait :
383
 
        unit -> unit;  (** Start the event loop *)
384
 
    }
385
 
(** There are two record components:
386
 
 *
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.
393
 
 *
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.
399
 
 *
400
 
 *   The callback function can change the list of interesting events by
401
 
 *   calling [sys_register] again.
402
 
 *
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.
407
 
 *)
408
 
 
409
 
 
410
 
(* ******************************************************************** *)
411
294
(* **                            jobs                                ** *)
412
295
(* ******************************************************************** *)
413
296
 
647
530
   * happened, the function sets [job_status] to [Job_running].
648
531
   *)
649
532
 
650
 
 
651
 
val register_job :
652
 
      system_handler ->
653
 
      job_instance -> unit
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].
 
534
 *)
 
535
class type ['t] job_handler_engine_type = object
 
536
  inherit ['t] Uq_engines.engine
 
537
 
 
538
  method job : job
 
539
    (** Returns the called job *)
 
540
 
 
541
  method job_instance : job_instance
 
542
    (** Returns the job instance *)
 
543
end;;
 
544
 
 
545
 
 
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.
656
552
   *)
657
553
 
658
 
 
659
554
val finish_job :
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.
665
 
   *
666
 
   * Exceptions raised by the producer/consumer functions are not caught.
667
 
   * In this case, [finish_job] is restartable.
668
 
   *
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]
672
 
   * is equivalent to
673
 
   * {[
674
 
   *   register_job sys jobinst;
675
 
   *   sys.sys_wait()
676
 
   * ]}
 
556
  (** This creates a [job_engine] internally and runs until it is
 
557
   * finished, i.e. until the job has been executed.
 
558
   *
 
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
 
562
   * happens.
677
563
   *)
678
564
 
679
565
val call_job :
718
604
   * This function is not available for jobs in the mode [Same_as_caller].
719
605
   *)
720
606
 
721
 
val process_group_expects_signals : job_instance -> bool
722
 
  (** [true] iff the group has [mode=Background] and [forward_signals]. *)
723
 
 
724
607
type job_status =
725
608
    Job_running            (** All commands could be started, and at least
726
609
                            * one process is still running
774
657
   *    used by the [Sys] module). Default is [Sys.sigterm].
775
658
   *)
776
659
 
777
 
val abandon_job :
 
660
val cancel_job :
778
661
      ?signal:int ->              (* default: SIGTERM *)
779
662
      job_instance -> unit
780
663
  (** Tries to get rid of a running job. If the mode is [Same_as_caller], the
791
674
   *    used by the [Sys] module). Default is [Sys.sigterm].
792
675
   *)
793
676
 
794
 
val iter_job_instances :
795
 
      f:(job_instance -> unit) ->
796
 
        unit
797
 
  (** Iterates over the jobs in the list of active jobs and calls [f] for every
798
 
   * [job_instance].
799
 
   *)
800
 
 
801
 
val watch_for_zombies : unit -> unit
802
 
  (** Iterates over the jobs in the list of abandoned jobs, and removes
803
 
   * zombie processes. 
804
 
   *)
805
 
 
806
 
 
 
677
val abandon_job : ?signal:int -> job_instance -> unit
 
678
  (** {b Deprecated} name for [cancel_job] *)
807
679
 
808
680
exception Already_installed;;
809
681
  (** Raised when the job handlers are already installed *)
813
685
      ?catch_sigquit:bool ->     (* default: true *)
814
686
      ?catch_sigterm:bool ->     (* default: true *)
815
687
      ?catch_sighup:bool ->      (* default: true *)
816
 
      ?catch_sigchld:bool ->     (* default: true *)
817
 
      ?set_sigpipe:bool ->       (* default: true *)
818
688
      ?at_exit:bool ->           (* default: true *)
819
689
      unit ->
820
690
      unit
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
826
 
   *   is performed.
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
832
 
   *   is performed.
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
838
 
   *   avoided)
839
 
   * - The handler for SIGPIPE does nothing; note that a previous action
840
 
   *   is overwritten (the parameter is called [set_sigpipe] to stress this)
841
 
   *
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
846
 
   *   children processes
 
700
   *
 
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.
 
704
   *
 
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.
 
707
   *
 
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
 
713
   * overridden.
847
714
   *
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.
855
722
   *
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.
859
725
   *
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])
867
731
   *)
868
732
 
878
742
 * Unixqueue now, which is much more powerful.
879
743
 *)
880
744
 
881
 
 
882
 
(**/**)
883
 
 
884
 
val init_mt : (unit -> ((unit -> unit) * (unit -> unit))) -> unit
885
 
  (* private *)
 
745
(** Also no longer supported because the type [system_handler] is gone:
 
746
 
 
747
    {[type system_handler]}
 
748
 
 
749
    {[ type process_event ]}
 
750
 
 
751
    {[val wait : 
 
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: [] *)
 
759
      process list ->
 
760
        process_event list
 
761
    ]}
 
762
    {[val register_job : system_handler -> job_instance -> unit]}
 
763
 
 
764
    {[val iter_job_instances : f:(job_instance -> unit) ->  unit]}
 
765
 
 
766
    {[val watch_for_zombies : unit -> unit]}
 
767
 
 
768
    {[val process_group_expects_signals : job_instance -> bool]}
 
769
 
 
770
 *)
 
771
 
 
772
(** {1 Debugging} *)
 
773
 
 
774
module Debug : sig
 
775
  val enable : bool ref
 
776
    (** Enables {!Netlog}-style debugging of this module  *)
 
777
end
 
778
 
 
779
 
 
780
 
 
781