PreviousUpNext

15.3.521  src/lib/std/src/posix/spawn–premicrothread.api

## spawn--premicrothread.api    -- high-level api for spawning unix child processes.
#
# An API for running subprocesses which is richer than
# the portable one provided by Winix_Process__Premicrothread in
#
#     src/lib/std/src/winix/winix-process--premicrothread.api
#
# but simpler than the raw Posix api provided by Posix_Process in
#
#     src/lib/std/src/psx/posix-process.api

# Compiled by:
#     src/lib/std/src/standard-core.sublib



# This API is implemented in:
#     src/lib/std/src/posix/spawn--premicrothread.pkg

stipulate
    package bio =  data_file__premicrothread;                                                   # data_file__premicrothread             is from   src/lib/std/src/posix/data-file--premicrothread.pkg
    package fil =  file__premicrothread;                                                        # file__premicrothread                  is from   src/lib/std/src/posix/file--premicrothread.pkg
    package sig =  interprocess_signals;                                                        # interprocess_signals                  is from   src/lib/std/src/nj/interprocess-signals.pkg
    package u1b =  one_byte_unt;                                                                # one_byte_unt                          is from   src/lib/std/types-only/basis-structs.pkg
    package wt  =  winix_types;                                                                 # winix_types                           is from   src/lib/std/src/posix/winix-types.pkg
herein                                                                                          # winix_types                           is from   src/lib/std/src/win32/winix-types.pkg

    api Spawn__Premicrothread {
        #
        Process(X,Y,Z);                         # The type variables are the stream types for child's stdin/stdout/stderr streams, as seen by the parent process. (i.e., output,input,input).

        Exit_Status
          #
          = W_EXITED
          | W_EXITSTATUS u1b::Unt
          | W_SIGNALED   sig::Signal
          | W_STOPPED    sig::Signal
          ;

        Spawn_Option
          #
          = WITH_ENVIRONMENT List(String)               # Defaults to posixlib::environment().
          #
          | REDIRECT_STDIN_IN_CHILD   Bool              # Defaults to TRUE.
          | REDIRECT_STDOUT_IN_CHILD  Bool              # Defaults to TRUE.
          | REDIRECT_STDERR_IN_CHILD  Bool              # Defaults to FALSE.
          #
          | REDIRECT_STDERR_TO_STDOUT_IN_CHILD  Bool    # Defaults to FALSE.
          ;

        spawn_process
            :
            { executable: String,               # executable -- "/usr/bin/foo" or such.
              arguments:  List(String),         # Remaining arguments for executable.
              options:    List(Spawn_Option)    
            }
            ->
            Process(X,Y,Z);
            #
            # spawn_process is the call to start up a program in a subprocess.
            #
            # By default the subprocess inherits the parent's environment
            # and stderr unchanged;  stdin/stdout are redirected into pipes
            # leading to the parent process. This behavior may be changed
            # via the options
            #
            #     WITH_ENVIRONMENT List(String)         # Defaults to posixlib::environment().
            #     REDIRECT_STDIN_IN_CHILD   Bool        # Defaults to TRUE.
            #     REDIRECT_STDOUT_IN_CHILD  Bool        # Defaults to TRUE.
            #     REDIRECT_STDERR_IN_CHILD  Bool        # Defaults to FALSE.
            #
            # Once the subprocess is spawned, its redirected streams
            # may be opened for text or binary I/O via
            #
            #     get_stdin_to_child_as_text_stream:            Process( fil::Output_Stream, X, Y ) ->  fil::Output_Stream;
            #     get_stdin_to_child_as_binary_stream:          Process( bio::Output_Stream, X, Y ) ->  bio::Output_Stream;
            #
            #     get_stdout_from_child_as_text_stream:         Process( X, fil::Input_Stream,  Y ) ->  fil::Input_Stream;
            #     get_stdout_from_child_as_binary_stream:       Process( X, bio::Input_Stream,  Y ) ->  bio::Input_Stream;
            #
            #     get_stderr_from_child_as_text_stream:         Process( X, Y, fil::Input_Stream ) ->  fil::Input_Stream;
            #     get_stderr_from_child_as_binary_stream:       Process( X, Y, bio::Input_Stream ) ->  bio::Input_Stream;
            #
            #   
            # invoking get_text_input_stream_from/get_text_output_stream_to or
            # get_binary_input_stream_from/get_binary_output_stream_to:
            #
            #
            # forks/execs new process running 'executable'.
            # The new process will have parent's environment 
            # unless overridden by WITH_ENVIRONMENT option.     
            # arguments args prepended by the last arc in 'executable'
            # (following the Unix convention that the first argument
            # is the command name).
            # Returns an abstract type Process(X,Y,Z) which represents
            # the child process plus streams attached to
            # the child process stdin/stdout.
            #
            # Sample call:
            #
            #   new_process
            #       =
            #       spawn_process
            #         {
            #           executable => "/usr/bin/foo",                                                                           # Process to run.
            #           arguments  => [ "-x", "this", "that" ],                                                                 # argv for process. ("foo" will be prepended.)
            #           options    => [ WITH_ENVIRONMENT ["LOGNAME=cynbe", "SHELL=/bin/tcsh", "HOME=/pub/home/cynbe" ]  ]       # This is an example, if WITH_ENVIRONMENT is omitted parent environment is inherited unchanged.
            #         };
            #
            # Simple command searching can be obtained by using
            #     spawn_process_in_environment { executable => "/bin/sh", arguments => [ "-c", args ], options => [] };

        fork_process:   List(Spawn_Option) -> Null_Or( Process(X,Y,Z) );
            #
            # fork_process is basically just a spawn_process()
            # that doesn't do an exece(), so we wind up with the
            # subprocess being a clone of ourself.
            #
            # The child  sees a NULL return value,
            # the parent sees a (THE process) return value:
            #
            # For a lower-level (essentially unix-level) fork() call see
            #
            #     src/lib/std/src/psx/posix-process.api
            #     src/lib/std/src/psx/posix-process.pkg
            #
            # CAVEAT PROGRAMMER:   Mythryl is heavily multithreaded
            # and doing fork() without an immediate execve() is really
            # dubious in a multithreaded context -- see
            #
            #     http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
            #
            # Even *with* doing an immediate execve, issues like open
            # file descriptors can created nasty problems.

        

        bin_sh: String -> String;

        # Access to stdin/stdout/stderr of child process.
        # NB: These are available only if fork_process/spawn_process
        # redirected them.
        # By default stdin and stdout are redirected, stderr is not.
        # This behavior may be changed via the options
        #     REDIRECT_STDIN_IN_CHILD   Bool    # Defaults to TRUE.
        #     REDIRECT_STDOUT_IN_CHILD  Bool    # Defaults to TRUE.
        #     REDIRECT_STDERR_IN_CHILD  Bool    # Defaults to FALSE.
        #
        # The underlying files are set to be close-on-exec.

        get_stdin_to_child_as_text_stream:      Process( fil::Output_Stream, X, Y ) ->  fil::Output_Stream;
        get_stdin_to_child_as_binary_stream:    Process( bio::Output_Stream, X, Y ) ->  bio::Output_Stream;

        get_stdout_from_child_as_text_stream:   Process( X, fil::Input_Stream,  Y ) ->  fil::Input_Stream;
        get_stdout_from_child_as_binary_stream: Process( X, bio::Input_Stream,  Y ) ->  bio::Input_Stream;

        get_stderr_from_child_as_text_stream:   Process( X, Y, fil::Input_Stream  ) ->  fil::Input_Stream;
        get_stderr_from_child_as_binary_stream: Process( X, Y, bio::Input_Stream  ) ->  bio::Input_Stream;

        process_id_of: Process(X,Y,Z) -> Int;

        text_streams_of
            :
            Process
              ( fil::Output_Stream,
                fil::Input_Stream,
                fil::Input_Stream
              )
            ->
            { stdin_to_child:       fil::Output_Stream,
              stdout_from_child:    fil::Input_Stream
            };

        reap:  Process(X,Y,Z) -> wt::process::Status;
            #
            # Closes the associated streams and wait for the
            # child process to finish, then return its exit status.
            #
            # Note that even if the child process has already exited,
            # so that reap returns immediately,
            # the parent process should eventually reap it. Otherwise,
            # the process will remain a zombie and take a slot in the
            # process table.

        # kill (proc, signal)
        # sends the Posix signal to the associated process.

        kill:  (Process(X,Y,Z), sig::Signal) -> Void;

        exit:  u1b::Unt -> X;
    };
end;

# SML/NJ (unhelpfully) calls this file/package 'Unix'


## COPYRIGHT (c) 1995 AT&T Bell Laboratories.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext