CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
process_private.h
1#pragma once
2
3#include <cx/platform/base.h>
4#include <cx/sys/process.h>
5
6// Contract every platform backend implements. Enumeration and lookup do not need a Process at
7// all; the rest operate on one the platform layer created itself, so each backend can safely
8// downcast to its own subclass.
9
10// Fill out with a snapshot of every process on the machine. The array is already initialized.
11// Returns false only if the process list could not be read at all -- processes that vanish
12// while the snapshot is being built are skipped, and the call still succeeds.
13bool _procPlatformEnum(sa_ProcessInfo* out, flags_t flags);
14
15// Fill out with one process's details. out is already initialized. Returns false if the
16// process does not exist.
17bool _procPlatformGetInfo(ProcessInfo* out, ProcessID pid, flags_t flags);
18
19// Launch a program. Returns NULL and sets cxerr if it could not be started -- including when
20// the executable itself failed to start, which the Unix backend learns through an error pipe
21// rather than by discovering a child that immediately died.
22_Ret_opt_valid_ Process* _procPlatformLaunch(strref exe, sa_string args, const ProcessOpts* opts);
23
24// Wait for a process to finish, up to timeout microseconds. Only called when the outcome is not
25// already cached on the object.
26bool _procPlatformWait(Process* proc, int64 timeout);
27
28// Ask a process to stop (force = false) or kill it outright (force = true).
29bool _procPlatformTerminate(Process* proc, bool force);
30
31// Report the exit code for a process whose status is not already cached. Platforms that can
32// never answer for this process -- Unix, for anything cx did not fork -- set CX_NotSupported so
33// the caller can tell "cannot know" from "not finished yet".
34bool _procPlatformExitCode(Process* proc, int32* code);
35
36// Collect any launched children that have finished and cache their status on their handles.
37// Called from procLaunch, procWait and Process destroy. Until the watcher lands, this is the
38// only thing that reaps, so a finished child stays a zombie until the next process API call.
39void _procReapPending(void);
40
41// Attach to an already-running process. Returns NULL and sets cxerr on failure.
42_Ret_opt_valid_ Process* _procPlatformOpen(ProcessID pid);
43
44// Grow an enumeration array by one and hand back the new slot, with the fields whose "unknown"
45// value is not zero already set. Shared so every backend fills entries the same way.
46ProcessInfo* _procInfoPush(sa_ProcessInfo* out);
47
48// Ask the OS whether the process is still alive. Only called for a process whose outcome is
49// not already cached on the object. A process cx did not launch that is found to be gone has
50// that published on the handle, which is what lets procNotifyExit fire immediately for it.
51bool _procPlatformRunning(Process* proc);
52
53// ---- exit watcher -------------------------------------------------------------------------
54//
55// procwatch.c owns the registry, the single watcher thread and closure dispatch. Each platform
56// supplies only the mechanism for learning that a process finished.
57
58// Called by procwatch.c.
59
60// One-time setup of the platform's waiting mechanism. Returning false means this platform has
61// no watcher, and no thread is started -- callers fall back to the synchronous sweep.
62bool _procWatchPlatformInit(void);
63
64typedef enum ProcWatchAddResult {
65 PROCWATCH_Failed = 0, // could not watch it
66 PROCWATCH_Armed, // watching; the exit will be delivered through _procWatchCompleted
67 PROCWATCH_Gone, // a process cx did not launch has already finished; nothing to watch
68} ProcWatchAddResult;
69
70// Start or stop watching a process. The registry already holds a reference for the duration,
71// and proc->watchid is assigned before Add is called. Remove is called exactly once per
72// successful Add, by whichever of completion or cancellation takes the process off the
73// registry first.
74ProcWatchAddResult _procWatchPlatformAdd(Process* proc);
75void _procWatchPlatformRemove(Process* proc);
76
77// Block up to timeout microseconds for watched processes to finish, calling
78// _procWatchCompleted() for each. Must return early when _procWatchPlatformWake() is called, or
79// a newly registered process would not be waited on until this timed out.
80void _procWatchPlatformWait(int64 timeout);
81
82// Nudge a blocked _procWatchPlatformWait so it picks up a registration change.
83void _procWatchPlatformWake(void);
84
85// Called by the platform backends, from whatever thread noticed the exit. The exit status must
86// already be cached on the object. Hands the process to the watcher thread for dispatch, so no
87// user callback ever runs on a system thread.
88void _procWatchCompleted(Process* proc);
89
90// Looks up a watched process by registration id and returns it acquired, or NULL if it is no
91// longer watched. Backends whose wait returns a token rather than a pinned pointer use this, so
92// a registration cancelled while its event was in flight is dropped instead of touched.
93_Ret_opt_valid_ Process* _procWatchAcquire(int64 watchid);
94
95// Every watched process with this pid, acquired, appended to out (already initialized). For
96// backends that key registrations on the pid, where several handles can share one.
97void _procWatchAcquireByPid(sa_Process* out, int64 pid);
98
99// Called by the platform launch paths for every child cx forks, whether or not anyone asked to
100// be notified -- something has to reap it -- and by procNotifyExit for a process cx did not
101// launch. Registering a process that is already watched does nothing and returns true. Returns
102// true if the watcher took the process on, in which case the watcher is now its only reaper;
103// false means the caller must fall back to the synchronous sweep. For a process cx did not
104// launch that has already finished, publishes that and returns true.
105bool _procWatchRegister(Process* proc);
106
107// Publish a finished process's outcome on its handle. known is false when the process is gone
108// but its status could not be collected; the exit code then reads as PROC_ExitCodeUnknown. The
109// first publication wins, so this is safe to call from several places that noticed the exit.
110void _procPublishExit(Process* proc, bool known, int32 exitcode, int32 termsignal);
111
112#if defined(_PLATFORM_WIN)
113#include "cx/platform/win/win_sys_process.h"
114#elif defined(_PLATFORM_UNIX)
115#include "cx/platform/unix/unix_sys_process.h"
116#elif defined(_PLATFORM_WASM)
117#include "cx/platform/wasm/wasm_sys_process.h"
118#endif
Compiler and platform detection macros.
int64 ProcessID
Operating system process id.
Definition process.h:128
Launching, inspecting and controlling operating system processes.