ProcessMonitor

Forks and monitors a process. Notifies a client about STDOUT / STDERR events.

actor tag ProcessMonitor

Constructors

create

new tag create(
  auth: (AmbientAuth val | StartProcessAuth val),
  notifier: ProcessNotify iso,
  filepath: FilePath val,
  args: Array[String val] val,
  vars: Array[String val] val)
: ProcessMonitor tag^

Parameters

Returns


Public Behaviours

print

Print some bytes and append a newline.

be print(
  data: (String val | Array[U8 val] val))

Parameters


write

Write to STDIN of the child process.

be write(
  data: (String val | Array[U8 val] val))

Parameters


printv

Print an iterable collection of ByteSeqs.

be printv(
  data: ByteSeqIter val)

Parameters


writev

Write an iterable collection of ByteSeqs.

be writev(
  data: ByteSeqIter val)

Parameters


done_writing

Set the _done_writing flag to true. If the _pending is empty we can close the _stdin_write file descriptor.

be done_writing()

dispose

Terminate child and close down everything.

be dispose()

Public Functions

expect

A stdout call on the notifier must contain exactly qty bytes. If qty is zero, the call can contain any amount of data.

fun ref expect(
  qty: USize val = seq)
: None val

Parameters

Returns


Private Behaviours

_event_notify

Handle the incoming event.

be _event_notify(
  event: Pointer[AsioEvent val] tag,
  flags: U32 val,
  arg: U32 val)

Parameters


_read_again

Resume reading on file descriptor.

be _read_again(
  fd: U32 val)

Parameters


Private Functions

_child

We are now in the child process. We redirect STDIN, STDOUT and STDERR to their pipes and execute the command. The command is executed via execve which does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded. We've set the FD_CLOEXEC flag on all file descriptors to ensure that they are all closed automatically once @execve gets called.

fun box _child(
  path: String val,
  argp: Array[Pointer[U8 val] tag] ref,
  envp: Array[Pointer[U8 val] tag] ref)
: None val

Parameters

Returns


_parent

We're now in the parent process. We setup asio events for STDOUT and STDERR and close the file descriptors we don't need.

fun ref _parent()
: None val

Returns


_make_argv

Convert an array of String parameters into an array of C pointers to same strings.

fun box _make_argv(
  args: Array[String val] box)
: Array[Pointer[U8 val] tag] ref

Parameters

Returns


_dup2

Creates a copy of the file descriptor oldfd using the file descriptor number specified in newfd. If the file descriptor newfd was previously open, it is silently closed before being reused. If dup2() fails because of EINTR we retry.

fun box _dup2(
  oldfd: U32 val,
  newfd: U32 val)
: None val

Parameters

  • oldfd: U32 val
  • newfd: U32 val

Returns


_make_pipe

Creates a pipe, an unidirectional data channel that can be used for interprocess communication. We need to set the flag on the two file descriptors here to prevent capturing by another thread.

fun box _make_pipe(
  fd_flags: I32 val)
: (U32 val , U32 val) ?

Parameters

  • fd_flags: I32 val

Returns


_getflags

Get the string representation of flags set for a file descriptor

fun box _getflags(
  fd: U32 val)
: String box ?

Parameters

Returns


_set_fd

fun box _set_fd(
  fd: U32 val,
  flags: I32 val)
: None val ?

Parameters

Returns


_set_fl

fun box _set_fl(
  fd: U32 val,
  flags: I32 val)
: None val ?

Parameters

Returns


_print_final

fun ref _print_final(
  data: (String val | Array[U8 val] val))
: None val

Parameters

Returns


_kill_child

Terminate the child process.

fun box _kill_child()
: None val ?

Returns


_event_flags

Return all flags of an event as a string.

fun box _event_flags(
  flags: U32 val)
: String box

Parameters

  • flags: U32 val

Returns


_close_fd

Close a file descriptor.

fun ref _close_fd(
  fd: U32 val)
: None val

Parameters

Returns


_close

Close all pipes, unsubscribe events and wait for the child process to exit.

fun ref _close()
: None val

Returns


_try_shutdown

If neither stdout nor stderr are open we close down and exit.

fun ref _try_shutdown()
: None val

Returns


_pending_reads

Read from stdout while data is available. If we read 4 kb of data, send ourself a resume message and stop reading, to avoid starving other actors. It's safe to use the same buffer for stdout and stderr because of causal messaging. Events get processed one after another.

fun ref _pending_reads(
  fd: U32 val)
: Bool val

Parameters

Returns


_read_buf_size

fun ref _read_buf_size()
: None val

Returns


_write_final

Write as much as possible to the fd. Return false if not everything was written.

fun ref _write_final(
  data: (String val | Array[U8 val] val))
: Bool val

Parameters

Returns


_pending_writes

Send pending data. If any data can't be sent, keep it and mark fd as not writeable. Once set to false the _stdin_writeable flag can only be cleared here by processing the pending writes. If the _done_writing flag is set we close the _stdin_write fd once we've processed pending writes.

fun ref _pending_writes()
: Bool val

Returns