Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

os/processes.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library feature processes
#
# -----------------------------------------------------------------------


# effect for starting processes
#
public processes (ph os.Process_Handler, public running_processes container.Set os.process) : effect is


  # start a process with name, arguments and environment variables
  #
  module start(name String, args Sequence String, env_vars container.Map String String) =>
    (ph.start name args env_vars).bind p->
      (os.processes ph (running_processes ∪ (container.set_of_ordered [p]))).replace
      p



  # cleanup effect
  #
  public redef finally unit =>
    running_processes.for_each p->
      _ := wait p


  # wait for process to finish
  #
  # returns the exit code of the process or an error
  #
  module wait(p os.process) outcome u32
  pre running_processes.contains p
  =>
    (os.processes ph (running_processes ∖ (container.set_of_ordered [p]))).replace
    wait0 p


  # helper feature wait
  #
  wait0(p os.process) outcome u32 =>
    _ := fzE_pipe_close p.std_in = 0
    r := fzE_process_wait p.pid
    if r<0
      error "Waiting for process with id {p.pid} was unsuccessful."
    else
      # NYI: UNDER DEVELOPMENT: close these:
      # check fzE_pipe_close p.std_out = 0
      # check fzE_pipe_close p.std_err = 0
      r.as_u32



  # install
install_default =>

  h : os.Process_Handler is

    # start process with option to pass environment variables
    #
    # helper feature for start and `infix |`
    #
    public redef start(n String, args Sequence String, env_vars container.Map String String) outcome os.process
    =>
      # NYI: UNDER DEVELOPMENT: what about quotes(") ?

      sys => fuzion.sys
      NULL := [u8 0].internal_array.data

      # posix_spawn needs last arg to be NULL
      arg_data := array (Array u8) args.count+2 i->
        if i=0 then sys.c_string n else if i<=args.count then sys.c_string args[i-1] else NULL

      env_var_strings := env_vars
        .items
        .map x->
          k, v := x
          "$k=$v"
        .as_array

      # posix_spawn needs last arg to be NULL
      env_data := array (Array u8) env_var_strings.count+1 (i -> if i<env_var_strings.count then sys.c_string env_var_strings[i] else NULL)

      res_data := sys.internal_array_init i64 4

      if (fzE_process_create arg_data.internal_array.data arg_data.count env_data.internal_array.data env_data.count res_data.data) = -1
        error "*** error creating process $n, got error number: $fzE_last_error ***"
      else
        os.process res_data[0] res_data[1] res_data[2] res_data[3]

  (os.processes h (container.ps_set os.process).empty).default



# short-hand to processes effect
#
public processes processes =>
  install_default
  processes.env

last changed: 2025-07-10