PreviousUpNext

15.4.1135  src/lib/std/src/posix/threadkit-spawn.pkg

## threadkit-spawn.pkg

# Compiled by:
#     src/lib/std/standard.lib


# This is a threadkit version of the
# UNIX interface that is provided by lib7.




###            "If your happiness depends on what somebody else does,
###             I guess you do have a problem."
###
###                                       -- Richard Bach


# XXX BUGGO FIXME any concurrent code referencing 'exec' or 'Exec'
#                 probably needs to be fixed to reference 'threadkit_spawn' or 'Threadkit_Spawn' respectively

stipulate
    package drv =  threadkit_winix_text_file_io_driver_for_posix;       # threadkit_winix_text_file_io_driver_for_posix is from   src/lib/std/src/posix/threadkit-winix-text-file-io-driver-for-posix.pkg
    package mop =  mailop;                                              # mailop                                        is from   src/lib/src/lib/thread-kit/src/core-thread-kit/mailop.pkg
    package ts  =  thread_scheduler;                                    # thread_scheduler                              is from   src/lib/src/lib/thread-kit/src/core-thread-kit/thread-scheduler.pkg
    package pm  =  process_deathwatch;                                  # process_deathwatch                            is from   src/lib/src/lib/thread-kit/src/process-deathwatch.pkg
    package tkf =  threadkit_file;                                      # threadkit_file                                is from   src/lib/std/src/posix/threadkit-file.pkg
    #
    package pp  =  posix_1003_1b;                                       # posix_1003_1b                                 is from   src/lib/std/src/posix-1003.1b/posix-1003-1b.pkg
    package pe  =  posix_1003_1b;
    package pf  =  posix_1003_1b;
    package pio =  posix_1003_1b;
    package psx =  posix_1003_1b;                                       # posix_1003_1b                                 is from   src/lib/std/src/posix-1003.1b/posix-1003-1b.pkg
    package ss  =  substring;                                           # substring                                     is from   src/lib/std/substring.pkg
    package rs  =  runtime_signals;                                     # runtime_signals                               is from   src/lib/std/src/nj/runtime-signals.pkg
herein

    package   threadkit_spawn
    : (weak)  Threadkit_Spawn                                           # Threadkit_Spawn                               is from   src/lib/std/src/posix/threadkit-spawn.api
    {
        fun protect f x
            =
            {   rs::mask_signals rs::MASK_ALL;
                #
                y = (f x)
                    except ex
                        =
                        {   rs::unmask_signals  rs::MASK_ALL;
                            raise exception ex;
                        };

                rs::unmask_signals  rs::MASK_ALL;

                y;
            };

        fun fd_reader (filename:  String, fd:  pio::File_Descriptor)
            =
            drv::make_filereader { filename, fd };

        fun fd_writer (filename, fd)
            =
            drv::make_filewriter
                {
                  filename,
                  fd,
                  append_mode     =>  FALSE,
                  best_io_quantum =>  4096
                };

        fun open_out_fd (filename, fd)
            =
            tkf::make_outstream
              (
                tkf::pur::make_outstream
                  (
                    fd_writer (filename, fd),
                    io_exceptions::BLOCK_BUFFERING
                  )
              );

        fun open_in_fd (filename, fd)
            =
            tkf::make_instream
              (
                tkf::pur::make_instream
                  (
                    fd_reader (filename, fd),
                    ""
                  )
              );

        Process
            =
            PROCESS  {
                pid:           pp::Process_Id,
                from_stream:   tkf::Input_Stream,
                to_stream:     tkf::Output_Stream
            };


        fun spawn_process_in_environment (cmd, argv, env)               # XXX SUCKO FIXME This should be upgraded per src/lib/std/src/posix/spawn.pkg
            =
            {   p1 = pio::make_pipe ();
                p2 = pio::make_pipe ();

                fun close_pipes ()
                    =
                    {   pio::close  p1.outfd; 
                        pio::close  p1.infd;
                        pio::close  p2.outfd; 
                        pio::close  p2.infd;
                    };

                base = ss::to_string
                           (ss::get_suffix
                               .{ #c != '/'; }
                               (ss::from_string cmd)
                           );

                fun start_child ()
                    =
                    case (protect pp::fork ())
                        #
                        THE pid =>   pid;           #  parent 
                        #
                        NULL =>
                            {   oldin  = p1.infd;           newin  =  psx::int_to_fd 0;
                                oldout = p2.outfd;          newout =  psx::int_to_fd 1;

                                pio::close p1.outfd;
                                pio::close p2.infd;

                                if (oldin != newin)
                                    #
                                    pio::dup2 { old => oldin, new => newin };
                                    pio::close oldin;
                                fi;

                                if (oldout != newout)
                                    #
                                    pio::dup2 { old => oldout, new => newout };
                                    pio::close oldout;
                                fi;

                                pp::exece (cmd, base ! argv, env)
                                except
                                    ex = # The exec failed, so we
                                         # need to shut down the child:
                                         #
                                         pp::exit 0u128;
                             };
                    esac;

                tkf::flush  tkf::stdout;

                pid = {
                        ts::stop_thread_scheduler_timer();
                        start_child () before
                        ts::restart_thread_scheduler_timer();
                      }
                      except
                          whatever_exception
                            =
                            {   ts::restart_thread_scheduler_timer();
                                close_pipes();
                                raise exception  whatever_exception;
                            };

                from_stream =  open_in_fd  (base + "_exec_in",  p2.infd);
                to_stream   =  open_out_fd (base + "_exec_out", p1.outfd);

                # Close the child-side fds 
                #
                pio::close  p2.outfd;
                pio::close  p1.infd;

                # Set the fds close on exec:
                # 
                pio::setfd (p2.infd, pio::fd::flags  [ pio::fd::cloexec ]);
                pio::setfd (p1.outfd, pio::fd::flags [ pio::fd::cloexec ]);

                PROCESS { pid, from_stream, to_stream };
            };

        fun spawn_process (cmd, argv)
            =
            spawn_process_in_environment (cmd, argv, pe::environment());



        fun streams_of (PROCESS { from_stream, to_stream, ... } )
            =
            (from_stream, to_stream);

        fun spawn  cmd
            =
            {   process =  spawn_process  cmd;
                #
                (streams_of  process)
                    ->
                    (from_stream, to_stream);

                { from_stream, to_stream, process };
            };


        fun kill (PROCESS { pid, ... }, signal)
            =
            pp::kill (pp::K_PROC pid, signal);


        fun reap_mailop (PROCESS { pid, from_stream, to_stream } )
            =
            {   ts::disable_thread_switching ();
                #
                pm::add_pid  pid
                before
                    ts::reenable_thread_switching ();
            };

        reap =  mop::do_mailop  o  reap_mailop;
    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext