## Detach


## detach.DetachedRun


A launched detached run: its name, session-leader pid, and the log receiving its output.


Usage

``` python
detach.DetachedRun(
    name,
    pid,
    log_path,
)
```


#### Parameter Attributes


`name: str`  

`pid: int`  

`log_path: Path`  


#### Example

``` python
>>> run = await launch(["make", "corpus"], name="overnight")
>>> await wait(run.name)
```

0


## detach.launch()


Launch `command` as a detached, session-leader subprocess that outlives the caller.


Usage

``` python
detach.launch(command, *, name, on_spawn=None)
```


The command runs under `/bin/sh -c` with stdout and stderr appended to `logs_root/runs/<name>.log`; once it exits the wrapper writes the real exit code to `logs_root/runs/<name>.exit` -- a file separate from the shared log, so the detached child's stdout cannot forge it -- and [wait()](detach.md#athome.detach.wait) recovers the code from there. The configured `env_prefix_cmd` is prepended like a launchd agent.


#### Parameters


`command: Sequence[str]`  
The argv of the program to run.

`name: str`  
A unique name for the run; also names its log, pid, and exit files.

`on_spawn: Callable[[`<a href="detach.html#athome.detach.DetachedRun" class="gdls-link gdls-code"><code>DetachedRun</code></a>`], None] | None = None`  
Synchronous callback invoked with the run before post-spawn I/O.


#### Returns


<a href="detach.html#athome.detach.DetachedRun" class="gdls-link gdls-code"><code>DetachedRun</code></a>  
The launched run's name, pid, and log path.


#### Raises


<a href="detach.html#athome.detach.DetachError" class="gdls-link gdls-code"><code>DetachError</code></a>  
A live run already holds `name`.


## detach.wait()


Poll until the run's process has exited and its `.exit` file appears, then return that code.


Usage

``` python
detach.wait(name, *, poll=5.0, timeout=None)
```


Completion is proven by the process's real exit -- its pid is gone, per [running()](detach.md#athome.detach.running) -- together with the wrapper-written `<name>.exit` file, never by a line the detached child could print to the shared log. A child that forges an `ATHOME-RUN-DONE` line on stdout, or writes its own `.exit` file while still alive, cannot make this return early.


#### Parameters


`name: str`  
The run to wait on.

`poll: float = ``5.0`  
Seconds to sleep between polls.

`timeout: float | None = None`  
Give up after this many seconds; `None` waits indefinitely.


#### Returns


`int`  
The command's exit code.


#### Raises


`TimeoutError`  
`timeout` elapsed before the run finished.


## detach.running()


Return the pid of the live run named `name` (pid file + `kill -0`), or None if none is alive.


Usage

``` python
detach.running(name)
```


## detach.DetachError


Raised when a detached run cannot start -- most often a live run already owns the name.


Usage

``` python
detach.DetachError()
```
