1pub use crate::{
4 assign_child_to_windows_job, cancel_capture_reader, canonical_environment_pairs,
5 capture_reader_done, compat_shell_command, configure_exact_trace, configure_process_command,
6 configure_process_command_for_bounded_owner_death, configure_sync_contained_command,
7 configure_sync_daemon_command, configure_sync_daemon_command_with_inheritance,
8 configure_trampoline_command, current_executable_build_id, exact_trace_capability, exit_code,
9 monitor_console_windows, parent_has_console, prepare_capture_reader, set_process_name,
10 shell_command, soft_terminate_process_group, spawn_sync, spawn_sync_daemon,
11 spawn_sync_daemon_with_inheritance, start_descendant_monitor, start_exact_trace,
12 sync_child_native_handle, trampoline_exit_code, unix_mark_extra_fds_close_on_exec,
13 CaptureCancellation, TracedChild, WindowsJobHandle,
14};
15
16#[cfg(feature = "async-process")]
17pub use crate::{
18 PlatformChild, PlatformEmergencySignal, PlatformLifecycle, PlatformOutput, PlatformStdin,
19 SpawnSpec, StreamMode,
20};
21
22#[cfg(feature = "process-inspection")]
23pub use crate::{kill_tree, process_snapshot, process_snapshot_for_pid};
24
25#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
27pub struct ProcessCommandConfig {
28 pub creation_flags: Option<u32>,
29 pub create_process_group: bool,
30 pub nice: Option<i32>,
31 pub address_space_limit_bytes: Option<u64>,
32}
33
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
41pub struct DaemonExecInheritance {
42 descriptor: i32,
43}
44
45impl DaemonExecInheritance {
46 #[allow(dead_code)]
50 pub(crate) fn preserving_descriptor(descriptor: i32) -> Self {
51 Self { descriptor }
52 }
53
54 #[allow(dead_code)]
55 pub(crate) fn descriptor(self) -> i32 {
56 self.descriptor
57 }
58}
59
60#[derive(Clone, Debug, Eq, PartialEq)]
62pub struct ExactTraceCapability {
63 pub available: bool,
64 pub backend: &'static str,
65 pub reason: &'static str,
66 pub non_invasive_backend: &'static str,
67 pub non_invasive_grade: NonInvasiveObservationGrade,
68}
69
70#[derive(Clone, Copy, Debug, Eq, PartialEq)]
71pub enum NonInvasiveObservationGrade {
72 KernelNotification,
73 KernelHintReconciled,
74 SnapshotInferred,
75}
76
77#[derive(Clone, Debug, Default, Eq, PartialEq)]
79pub struct TraceOriginArtifact {
80 pub origin_pid: u32,
81 pub thread_id: u32,
82 pub architecture: String,
83 pub register_format: String,
84 pub executable: Option<std::path::PathBuf>,
85 pub registers: Vec<u8>,
86 pub stack_pointer: Option<u64>,
87 pub instruction_pointer: Option<u64>,
88 pub stack: Vec<u8>,
89 pub truncated: bool,
90 pub module_map: Vec<u8>,
91 pub module_map_truncated: bool,
92}
93
94#[derive(Clone, Debug, Eq, PartialEq)]
96pub struct ExactTraceEvent {
97 pub sequence: u64,
98 pub pid: u32,
99 pub parent_pid: Option<u32>,
100 pub parent_start_key: Option<u64>,
101 pub start_key: Option<u64>,
102 pub timestamp: std::time::SystemTime,
103 pub kind: ExactTraceEventKind,
104 pub executable: Option<std::path::PathBuf>,
105 pub argv: Option<Vec<std::ffi::OsString>>,
106 pub origin: Option<TraceOriginArtifact>,
107}
108
109#[derive(Clone, Debug, Eq, PartialEq)]
110pub enum ExactTraceEventKind {
111 Spawn,
112 Exec,
113 Exit {
114 exit_code: Option<i32>,
115 signal: Option<i32>,
116 raw_status: i64,
117 },
118 Loss {
119 reason: String,
120 },
121}
122
123#[derive(Clone, Copy, Debug, Eq, PartialEq)]
125pub enum DescendantEvent {
126 Started {
127 pid: u32,
128 parent_pid: Option<u32>,
134 },
135 Exited(u32),
136 Completed,
139}
140
141pub struct DescendantMonitorStop {
143 stopped: std::sync::atomic::AtomicBool,
144 mutex: std::sync::Mutex<()>,
145 wake: std::sync::Condvar,
146}
147
148impl DescendantMonitorStop {
149 pub fn new() -> Self {
151 Self {
152 stopped: std::sync::atomic::AtomicBool::new(false),
153 mutex: std::sync::Mutex::new(()),
154 wake: std::sync::Condvar::new(),
155 }
156 }
157
158 pub fn is_stopped(&self) -> bool {
160 self.stopped.load(std::sync::atomic::Ordering::Acquire)
161 }
162
163 pub fn stop(&self) {
165 let _guard = self.mutex.lock().unwrap_or_else(|error| error.into_inner());
166 if !self.stopped.swap(true, std::sync::atomic::Ordering::AcqRel) {
167 self.wake.notify_all();
168 }
169 }
170
171 pub fn wait_timeout(&self, timeout: std::time::Duration) -> bool {
173 if self.is_stopped() {
174 return true;
175 }
176 let guard = self.mutex.lock().unwrap_or_else(|error| error.into_inner());
177 if self.is_stopped() {
178 return true;
179 }
180 let (_guard, _wait_result) = self
181 .wake
182 .wait_timeout(guard, timeout)
183 .unwrap_or_else(|error| error.into_inner());
184 self.is_stopped()
185 }
186}
187
188impl Default for DescendantMonitorStop {
189 fn default() -> Self {
190 Self::new()
191 }
192}
193
194#[derive(Clone, Copy)]
196pub enum CaptureStream {
197 Stdout,
198 Stderr,
199}
200
201#[derive(Debug, Clone)]
203pub struct ConsoleWindowInfo {
204 pub pid: u32,
205 pub title: String,
206 pub hwnd: u64,
207}
208
209#[derive(Clone, Copy, Debug, Eq, PartialEq)]
213pub struct ProcessSnapshot {
214 pub pid: u32,
215 pub parent_pid: u32,
216 pub start_time_a: u64,
217 pub start_time_b: u64,
218}
219
220#[derive(Clone, Debug, Eq, PartialEq)]
225pub enum SyncEnvironment {
226 Inherit,
228 Explicit(Vec<(std::ffi::OsString, std::ffi::OsString)>),
230}
231
232pub struct SpawnStdio<'a> {
238 pub stdin: StdioSource<'a>,
240 pub stdout: StdioSource<'a>,
242 pub stderr: StdioSource<'a>,
244 pub drain_timeout: Option<std::time::Duration>,
246 pub show_console: bool,
248}
249
250impl Default for SpawnStdio<'_> {
251 fn default() -> Self {
252 Self {
253 stdin: StdioSource::Null,
254 stdout: StdioSource::Parent,
255 stderr: StdioSource::Parent,
256 drain_timeout: Some(std::time::Duration::from_secs(2)),
257 show_console: false,
258 }
259 }
260}
261
262pub struct DaemonStdio<'a> {
268 pub stdout: DaemonStdioSource<'a>,
270 pub stderr: DaemonStdioSource<'a>,
272}
273
274impl Default for DaemonStdio<'_> {
275 fn default() -> Self {
276 Self {
277 stdout: DaemonStdioSource::Null,
278 stderr: DaemonStdioSource::Null,
279 }
280 }
281}
282
283pub enum DaemonStdioSource<'a> {
285 Null,
287 File(&'a std::fs::File),
289}
290
291pub enum StdioSource<'a> {
293 Null,
295 Parent,
297 File(&'a std::fs::File),
299 Pipe,
301}
302
303pub struct DaemonChild {
305 pub(crate) pid: u32,
306 pub(crate) inner: Box<dyn DaemonChildControl>,
307}
308
309pub(crate) trait DaemonChildControl:
310 Send + Sync + std::panic::UnwindSafe + std::panic::RefUnwindSafe
311{
312 fn kill(&mut self) -> std::io::Result<()>;
313 fn wait(&mut self) -> std::io::Result<i32>;
314 fn try_wait(&mut self) -> std::io::Result<Option<i32>>;
315}
316
317impl DaemonChild {
318 pub fn id(&self) -> u32 {
320 self.pid
321 }
322
323 pub fn kill(&mut self) -> std::io::Result<()> {
325 self.inner.kill()
326 }
327
328 pub fn wait(&mut self) -> std::io::Result<i32> {
330 self.inner.wait()
331 }
332
333 pub fn try_wait(&mut self) -> std::io::Result<Option<i32>> {
335 self.inner.try_wait()
336 }
337}
338
339pub struct SpawnedChild {
343 pub(crate) kill_on_drop: bool,
344 pub stdin: Option<std::process::ChildStdin>,
346 pub stdout: Option<std::process::ChildStdout>,
348 pub stderr: Option<std::process::ChildStderr>,
350 pub(crate) pid: u32,
351 pub(crate) inner: Box<dyn SpawnedChildControl>,
352}
353
354pub(crate) trait SpawnedChildControl:
355 Send + Sync + std::panic::UnwindSafe + std::panic::RefUnwindSafe
356{
357 fn kill(&mut self) -> std::io::Result<()>;
358 fn wait(&mut self) -> std::io::Result<i32>;
359 fn try_wait(&mut self) -> std::io::Result<Option<i32>>;
360 fn shutdown(&mut self);
361 #[cfg(feature = "independent-spawn")]
362 fn retain_exit_identity(&mut self) {}
363 #[cfg(feature = "independent-spawn")]
364 fn detach(&mut self) -> std::io::Result<()> {
365 Ok(())
366 }
367 #[cfg(feature = "independent-spawn")]
368 fn kill_tree(&mut self) -> std::io::Result<()> {
369 self.kill()
370 }
371}
372
373impl SpawnedChild {
374 #[cfg(feature = "independent-spawn")]
375 pub(crate) fn retain_exit_identity(&mut self) {
376 self.inner.retain_exit_identity();
377 }
378 #[cfg(feature = "independent-spawn")]
379 pub(crate) fn commit_detached(&mut self) -> std::io::Result<()> {
380 self.inner.detach()?;
381 self.kill_on_drop = false;
382 Ok(())
383 }
384 #[cfg(feature = "independent-spawn")]
385 pub(crate) fn kill_tree(&mut self) -> std::io::Result<()> {
386 self.inner.kill_tree()
387 }
388 pub fn id(&self) -> u32 {
390 self.pid
391 }
392
393 pub fn kill(&mut self) -> std::io::Result<()> {
395 self.inner.kill()
396 }
397
398 pub fn wait(&mut self) -> std::io::Result<i32> {
400 self.inner.wait()
401 }
402
403 pub fn try_wait(&mut self) -> std::io::Result<Option<i32>> {
405 self.inner.try_wait()
406 }
407}
408
409impl Drop for SpawnedChild {
410 fn drop(&mut self) {
411 if self.kill_on_drop {
412 self.inner.shutdown();
413 }
414 }
415}
416
417#[derive(Clone, Copy)]
418pub enum ObserverScope {
419 SystemWide,
420 LaunchedProcessTree,
421}
422#[derive(Clone, Copy)]
423pub enum ObserverCategory {
424 File,
425 Network,
426 Process,
427}
428#[derive(Clone, Copy)]
429pub enum ObserverSupport {
430 Supported,
431 Partial,
432 Unavailable,
433}
434#[derive(Clone, Copy)]
435pub struct ObserverBackend {
436 pub support: ObserverSupport,
437 pub backend: &'static str,
438 pub reason: &'static str,
439}
440pub use crate::platform_imp::observer_backend;
441pub use crate::platform_imp::read_process_argv;
442pub use crate::platform_imp::read_process_cmdline;
443pub use crate::platform_imp::read_process_file_handles;
444
445#[derive(Debug, Clone, Copy, PartialEq, Eq)]
447pub enum UnixSignalKind {
448 Interrupt,
449 Terminate,
450 Kill,
451}
452
453pub use crate::{
454 unix_set_priority, unix_signal_process, unix_signal_process_group, unix_signal_raw,
455};
456
457#[derive(Debug, Clone, Copy, PartialEq, Eq)]
465pub enum OwnerDeathCleanup {
466 OwnerDeathSignal,
468 KillOnOwnerHandleClose,
470 AlreadyContained,
472 SupervisorRequired,
474 Unsupported,
476}
477
478#[derive(Debug, Clone, Copy, PartialEq, Eq)]
486pub enum OwnerDeathCleanupStage {
487 RequestSignal,
489 CreateContainer,
491 JoinContainer,
493}
494
495#[derive(Debug)]
497pub struct OwnerDeathCleanupError {
498 pub stage: OwnerDeathCleanupStage,
500 pub source: std::io::Error,
502}
503
504impl std::fmt::Display for OwnerDeathCleanupError {
505 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
506 write!(f, "{:?}: {}", self.stage, self.source)
507 }
508}
509
510impl std::error::Error for OwnerDeathCleanupError {
511 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
512 Some(&self.source)
513 }
514}
515
516pub use crate::{
517 process_install_owner_death_cleanup as install_owner_death_cleanup,
518 process_owner_death_cleanup_target as owner_death_cleanup_target,
519};
520
521#[derive(Debug, Clone, Copy, PartialEq, Eq)]
528pub enum ProcessInspectErrorKind {
529 InvalidPid,
531 NotFound,
533 Unsupported,
535 Host,
537}
538
539#[derive(Debug)]
541pub struct ProcessInspectError {
542 pub kind: ProcessInspectErrorKind,
544 pub source: std::io::Error,
546}
547
548impl ProcessInspectError {
549 pub fn last_os_error(kind: ProcessInspectErrorKind) -> Self {
551 Self {
552 kind,
553 source: std::io::Error::last_os_error(),
554 }
555 }
556
557 pub fn stated(kind: ProcessInspectErrorKind, message: &str) -> Self {
559 Self {
560 kind,
561 source: std::io::Error::other(message.to_string()),
562 }
563 }
564}
565
566impl std::fmt::Display for ProcessInspectError {
567 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
568 write!(f, "{:?}: {}", self.kind, self.source)
569 }
570}
571
572impl std::error::Error for ProcessInspectError {
573 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
574 Some(&self.source)
575 }
576}
577
578pub use crate::{
579 process_executable_path as executable_path, process_force_kill as force_kill,
580 process_same_executable_path as same_executable_path,
581 process_signal_terminate as signal_terminate, ProcessLiveness,
582};
583
584pub struct ShutdownRequest {
596 flag: &'static std::sync::atomic::AtomicBool,
597}
598
599impl ShutdownRequest {
600 pub fn watching(flag: &'static std::sync::atomic::AtomicBool) -> Self {
611 Self { flag }
612 }
613
614 pub fn requested(&self) -> bool {
620 self.flag.load(std::sync::atomic::Ordering::Relaxed)
621 }
622}
623
624impl std::fmt::Debug for ShutdownRequest {
625 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
626 f.debug_struct("ShutdownRequest")
627 .field("requested", &self.requested())
628 .finish()
629 }
630}
631
632pub use crate::process_install_shutdown_request_handler as install_shutdown_request_handler;
633
634pub use crate::{
646 process_can_replace_current_image as can_replace_current_image,
647 process_replace_current_image as replace_current_image,
648};