Process Management
Spawn, monitor, and communicate with child processes. Implements actor-model patterns with message passing, supervision, and lifecycle management.
The process global is always available.
Process Information
Get the current frame ID or process ID:
local frame_id = process.id() -- Call chain identifier
local pid = process.pid() -- Process ID
Sending Messages
Send message(s) to a process by PID or registered name:
local ok, err = process.send(destination, topic, ...)
| Parameter | Type | Description |
|---|---|---|
destination |
string | PID or registered name |
topic |
string | Topic name (cannot start with @) |
... |
any | Payload values |
Permission: process.send on target PID
Spawning Processes
-- Basic spawn
local pid, err = process.spawn(id, host, ...)
-- With monitoring (receive EXIT events)
local pid, err = process.spawn_monitored(id, host, ...)
-- With linking (receive LINK_DOWN on abnormal exit)
local pid, err = process.spawn_linked(id, host, ...)
-- Both linked and monitored
local pid, err = process.spawn_linked_monitored(id, host, ...)
| Parameter | Type | Description |
|---|---|---|
id |
string | Process source ID (e.g., "app.workers:handler") |
host |
string | Host ID (e.g., "app:processes") |
... |
any | Arguments passed to spawned process |
Permissions:
process.spawnon process idprocess.hoston host idprocess.spawn.monitoredon process id (for monitored variants)process.spawn.linkedon process id (for linked variants)
Process Control
-- Forcefully terminate a process
local ok, err = process.terminate(destination)
-- Request graceful cancellation with optional deadline
local ok, err = process.cancel(destination, "5s")
| Parameter | Type | Description |
|---|---|---|
destination |
string | PID or registered name |
deadline |
string|integer | Duration string or milliseconds |
Permissions: process.terminate, process.cancel on target PID
Monitoring and Linking
Monitor or link to an existing process:
-- Monitoring: receive EXIT events when target exits
local ok, err = process.monitor(destination)
local ok, err = process.unmonitor(destination)
-- Linking: bidirectional, receive LINK_DOWN on abnormal exit
local ok, err = process.link(destination)
local ok, err = process.unlink(destination)
Permissions: process.monitor, process.unmonitor, process.link, process.unlink on target PID
Process Options
local options = process.get_options()
local ok, err = process.set_options({trap_links = true})
| Field | Type | Description |
|---|---|---|
trap_links |
boolean | Whether LINK_DOWN events are delivered to events channel |
Inbox and Events
Get channels for receiving messages and lifecycle events:
local inbox = process.inbox() -- Message objects from @inbox topic
local events = process.events() -- Lifecycle events from @events topic
Event Types
| Constant | Description |
|---|---|
process.event.CANCEL |
Cancellation requested |
process.event.EXIT |
Monitored process exited |
process.event.LINK_DOWN |
Linked process terminated abnormally |
Event Fields
| Field | Type | Description |
|---|---|---|
kind |
string | Event type constant |
from |
string | Source PID |
result |
table | For EXIT: {value: any} or {error: string} |
deadline |
string | For CANCEL: deadline timestamp |
Topic Subscription
Subscribe to custom topics:
local ch = process.listen(topic, options)
process.unlisten(ch)
| Parameter | Type | Description |
|---|---|---|
topic |
string | Topic name (cannot start with @) |
options.message |
boolean | If true, receive Message objects; if false, raw payloads |
Message Objects
When receiving from inbox or with {message = true}:
local msg = inbox:receive()
msg:topic() -- string: topic name
msg:from() -- string|nil: sender PID
msg:payload() -- any: payload data
Synchronous Call
Spawn a process, wait for its result, and return:
local result, err = process.call(id, host, ...)
Permissions: process.call on process id, process.host on host id
Process Upgrade
Upgrade the current process to a new definition while preserving PID:
-- Upgrade to new version, passing state
process.upgrade(source, ...)
-- Keep same definition, re-run with new state
process.upgrade(nil, preserved_state)
Context Spawner
Create a spawner with custom context for child processes:
local spawner = process.with_context({request_id = "123"})
Permission: process.context on "context"
SpawnBuilder Methods
SpawnBuilder is immutable - each method returns a new instance:
spawner:with_context(values) -- Add context values
spawner:with_actor(actor) -- Set security actor
spawner:with_scope(scope) -- Set security scope
spawner:with_name(name) -- Set process name
spawner:with_message(topic, ...) -- Queue message to send after spawn
Permission: process.security on "security" for :with_actor() and :with_scope()
Spawner Spawn Methods
spawner:spawn(id, host, ...)
spawner:spawn_monitored(id, host, ...)
spawner:spawn_linked(id, host, ...)
spawner:spawn_linked_monitored(id, host, ...)
Same permissions as module-level spawn functions.
Name Registry
Register and lookup processes by name:
local ok, err = process.registry.register(name, pid) -- pid defaults to self
local pid, err = process.registry.lookup(name)
local ok = process.registry.unregister(name)
Permissions: process.registry.register, process.registry.unregister on name
Permissions
Permissions control what a calling process can do. All checks use the caller's security context (actor) against the target resource.
Policy Evaluation
Policies can allow/deny based on:
- Actor: The security principal making the request
- Action: The operation being performed (e.g.,
process.send) - Resource: The target (PID, process id, host id, or name)
- Attributes: Additional context including
pid(caller's process ID)
Permission Reference
| Permission | Functions | Resource |
|---|---|---|
process.spawn |
spawn*() |
process id |
process.spawn.monitored |
spawn_monitored(), spawn_linked_monitored() |
process id |
process.spawn.linked |
spawn_linked(), spawn_linked_monitored() |
process id |
process.host |
spawn*(), call() |
host id |
process.send |
send() |
target PID |
process.call |
call() |
process id |
process.terminate |
terminate() |
target PID |
process.cancel |
cancel() |
target PID |
process.monitor |
monitor() |
target PID |
process.unmonitor |
unmonitor() |
target PID |
process.link |
link() |
target PID |
process.unlink |
unlink() |
target PID |
process.context |
with_context() |
"context" |
process.security |
:with_actor(), :with_scope() |
"security" |
process.registry.register |
registry.register() |
name |
process.registry.unregister |
registry.unregister() |
name |
Multiple Permissions
Some operations require multiple permissions:
| Operation | Required Permissions |
|---|---|
spawn() |
process.spawn + process.host |
spawn_monitored() |
process.spawn + process.spawn.monitored + process.host |
spawn_linked() |
process.spawn + process.spawn.linked + process.host |
spawn_linked_monitored() |
process.spawn + process.spawn.monitored + process.spawn.linked + process.host |
call() |
process.call + process.host |
| spawn with custom actor/scope | spawn permissions + process.security |
Errors
| Condition | Kind |
|---|---|
| No context found | errors.INVALID |
| Frame context not found | errors.INVALID |
| Missing required arguments | errors.INVALID |
Reserved topic prefix (@) |
errors.INVALID |
| Invalid duration format | errors.INVALID |
| Name not registered | errors.NOT_FOUND |
| Permission denied | errors.PERMISSION_DENIED |
| Name already registered | errors.ALREADY_EXISTS |
See Error Handling for working with errors.
See Also
- Channels - Inter-process communication
- Message Queue - Queue-based messaging
- Functions - Function invocation
- Supervision - Process lifecycle management