]> xenbits.xensource.com Git - xcp/xen-api-libs.git/commitdiff
[ocamldoc]: attempt to tidy-up the ocamldoc comments in the forkhelpers module
authorDavid Scott <dave.scott@eu.citrix.com>
Tue, 22 Dec 2009 11:37:00 +0000 (11:37 +0000)
committerDavid Scott <dave.scott@eu.citrix.com>
Tue, 22 Dec 2009 11:37:00 +0000 (11:37 +0000)
Signed-off-by: David Scott <dave.scott@eu.citrix.com>
stdext/forkhelpers.mli

index bedb87e8f3c4490af7e4462aaa23be142eaf96d4..b7754ee67c5d97e1a7272bf0aed8ba914149f3e0 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *)
-(* Functions to safely fork potentially long-running sub-processes without
-   leaking file descriptors or accidentally deadlocking the parent process. *)
+
+(** Functions to execute processes, pass file descriptors around and return results *)
+
+(** The low-level Unix.fork(), Unix.exec*() functions and friends are not safe to 
+    call in multithreaded programs for two reasons:
+    + parallel threads opening new file descriptors will have these descriptors captured
+      by a fork(). This leads to annoying glitches like (for example) attempts to 'umount'
+      a filesystem being rejected because a file is still open.
+    + although Unix.fork() will call (via the ocaml runtime) a pthread_atfork handler
+      which attempts to clean up the state of the threading system in the child, this relies
+      on quite a complex glibc implementation.
+
+    Additionally Unix.fork(), Unix.exec*() are very low-level primitives. When we call
+    these functions what we actually want to do is run some separate process with certain
+    file-descriptors, optionally returning results. 
+
+       The interface in this module
+    + is higher-level than Unix.fork(), Unix.exec*()
+    + allows us to offload Unix.fork(), Unix.exec*() to a single-threaded separate process
+      where the glibc+ocaml runtime codepaths are simpler and hopefully more reliable. *)
+
+(** { 1 High-level interface } *)
 
 (** [execute_command_get_output cmd args] runs [cmd args] and returns (stdout, stderr)
-       on success (exit 0). On failure this raises [Spawn_internal_error(stderr, stdout, Unix.process_status)]
-*)
+       on success (exit 0). On failure this raises 
+    [Spawn_internal_error(stderr, stdout, Unix.process_status)] *)
 val execute_command_get_output : ?env:string array -> string -> string list -> string * string
 
 (** Thrown by [execute_command_get_output] if the subprocess exits with a non-zero exit code *)
 exception Spawn_internal_error of string * string * Unix.process_status
 
+(** { 2 Low-level interface } *)
+
 (** Represents a forked process *)
 type pidty
 
@@ -33,6 +55,7 @@ val getpid : pidty -> int
 
 (** Thrown by [safe_close_and_exec] if the process exits with a non-zero exit code. *)
 exception Subprocess_failed of int
+
 (** Thrown by [safe_close_and_exec] if the process exits due to a signal *)
 exception Subprocess_killed of int
 
@@ -44,18 +67,21 @@ val safe_close_and_exec : ?env:string array -> Unix.file_descr option -> Unix.fi
 
 (** [waitpid p] returns the (pid, Unix.process_status) *)
 val waitpid : pidty -> (int * Unix.process_status)
+
 (** [waitpid_nohang p] returns the (pid, Unix.process_status) if the process has already
        quit or (0, Unix.WEXITTED 0) if the process is still running. *)
 val waitpid_nohang : pidty -> (int * Unix.process_status)
+
 (** [dontwaitpid p]: signals the caller's desire to never call waitpid. Note that the final
        process will not persist as a zombie. *)
 val dontwaitpid : pidty -> unit
+
 (** [waitpid_fail_if_bad_exit p] calls waitpid on [p] and throws [Subprocess_failed x] if the 
        process exits with non-zero code x and [Subprocess_killed x] if the process is killed by a 
        signal and exits with non-zero code x. *)
 val waitpid_fail_if_bad_exit : pidty -> unit
 
-
+(** result returned by [with_logfile_fd] *)
 type 'a result = Success of string * 'a | Failure of string * exn
 
 (** Creates a temporary file and opens it for logging. The fd is passed to the function