# `Portals.WorkerLifecycle.Port`
[🔗](https://github.com/Ziinc/portals/blob/v0.1.0/lib/portals/worker_lifecycle/port.ex#L1)

Launches and monitors the direct worker process through a BEAM Port
(FR-1). Owns only the direct child process — descendant processes the
worker itself spawns are not tracked or reaped; applications that need
process-tree ownership must wrap the worker in a container or process
group of their own.

Two transport modes:

  * `:unix` (default) — the port is opened only for lifecycle
    monitoring (`:exit_status`) and to observe stray stdout/stderr as
    diagnostic output; RPC data flows over a separate
    `Portals.Transport.Unix` socket.
  * `:stdio` — the port itself carries framed RPC data
    (`{:packet, 4}`); it is opened by `Portals.Connection`, not here,
    since the transport and the port are the same resource in that mode.

# `launch_opts`

```elixir
@type launch_opts() :: [
  command: binary(),
  args: [binary()],
  env: [{binary(), binary()}],
  cd: binary()
]
```

# `launch`

```elixir
@spec launch(launch_opts()) :: {:ok, port()} | {:error, term()}
```

Launch the worker for the `:unix` transport mode: the port is used only
to detect process exit, never for data. No shell is involved —
`spawn_executable` receives the resolved absolute path and an explicit
argument list.

# `launch_stdio`

```elixir
@spec launch_stdio(launch_opts()) :: {:ok, port()} | {:error, term()}
```

Launch the worker for the `:stdio` transport mode: the port itself is the framed data channel.

# `os_pid`

```elixir
@spec os_pid(port()) :: {:ok, non_neg_integer()} | :error
```

The OS process id of a launched worker, when available.

# `terminate`

```elixir
@spec terminate(port(), non_neg_integer()) :: :ok
```

Gracefully terminate: assumes the caller has already asked the worker to
exit cooperatively (e.g. by sending a `SHUTDOWN` frame over RPC) and
waits up to `deadline_ms` for the port to report `{:exit_status, _}`.
If the deadline elapses, sends `SIGKILL` to the OS process directly
(never to any descendant it may itself have spawned) and closes the port.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
