Skip to content

ProcessMonitor

[Source]

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

actor tag ProcessMonitor

Constructors

create

[Source]

Create infrastructure to communicate with a forked child process and register the asio events. Fork child process and notify our user about incoming data via the notifier.

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

Parameters

Returns


Public Behaviours

print

[Source]

Print some bytes and append a newline.

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

Parameters


write

[Source]

Write to STDIN of the child process.

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

Parameters


printv

[Source]

Print an iterable collection of ByteSeqs.

be printv(
  data: ByteSeqIter val)

Parameters


writev

[Source]

Write an iterable collection of ByteSeqs.

be writev(
  data: ByteSeqIter val)

Parameters


done_writing

[Source]

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

be done_writing()

dispose

[Source]

Terminate child and close down everything.

be dispose()

Public Functions

expect

[Source]

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

[Source]

Handle the incoming event.

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

Parameters


_read_again

[Source]

Resume reading on file descriptor.

be _read_again(
  fd: U32 val)

Parameters


Private Functions

_child

[Source]

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

[Source]

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

[Source]

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

[Source]

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

[Source]

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

[Source]

Get the string representation of flags set for a file descriptor

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

Parameters

Returns


_set_fd

[Source]

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

Parameters

Returns


_set_fl

[Source]

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

Parameters

Returns


_print_final

[Source]

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

Parameters

Returns


_kill_child

[Source]

Terminate the child process, first trying SIGTERM and if that fails try SIGKILL.

fun box _kill_child()
: None val

Returns


_event_flags

[Source]

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

[Source]

Close a file descriptor. This function also handles unsubscribing the asio event (if the file descriptor has one), the file descriptor should always be closed after unsubscribing the event, otherwise there is the possibility of reusing the file descriptor in another thread and then unsubscribing the reused file descriptor here! Unsubscribing and closing the file descriptor should be treated as one operation, and as this function is called from many places in this module put the unsubscribing logic here too.

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

Parameters

Returns


_close

[Source]

Close all pipes wait for the child process to exit.

fun ref _close()
: None val

Returns


_try_shutdown

[Source]

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

fun ref _try_shutdown()
: None val

Returns


_pending_reads

[Source]

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

[Source]

fun ref _read_buf_size()
: None val

Returns


_write_final

[Source]

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

[Source]

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