Skip to main content

servo_constellation/
process_manager.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::process::Child;
6
7use crossbeam_channel::{Receiver, Select};
8use log::{debug, warn};
9use profile_traits::mem::{ProfilerChan, ProfilerMsg};
10use servo_base::generic_channel::SendError;
11
12pub enum Process {
13    Unsandboxed(Child),
14    Sandboxed(u32),
15}
16
17impl Process {
18    fn pid(&self) -> u32 {
19        match self {
20            Self::Unsandboxed(child) => child.id(),
21            Self::Sandboxed(pid) => *pid,
22        }
23    }
24
25    fn wait(&mut self) {
26        match self {
27            Self::Unsandboxed(child) => {
28                let _ = child.wait();
29            },
30            Self::Sandboxed(_pid) => {
31                // TODO: use nix::waitpid() on supported platforms.
32                warn!("wait() is not yet implemented for sandboxed processes.");
33            },
34        }
35    }
36}
37
38type ProcessReceiver = Receiver<Result<(), SendError>>;
39
40pub(crate) struct ProcessManager {
41    processes: Vec<(Process, ProcessReceiver)>,
42    mem_profiler_chan: ProfilerChan,
43}
44
45impl ProcessManager {
46    pub fn new(mem_profiler_chan: ProfilerChan) -> Self {
47        Self {
48            processes: vec![],
49            mem_profiler_chan,
50        }
51    }
52
53    pub fn add(&mut self, receiver: ProcessReceiver, process: Process) {
54        debug!("Adding process pid={}", process.pid());
55        self.processes.push((process, receiver));
56    }
57
58    pub fn register<'a>(&'a self, select: &mut Select<'a>) {
59        for (_, receiver) in &self.processes {
60            select.recv(receiver);
61        }
62    }
63
64    pub fn receiver_at(&self, index: usize) -> &ProcessReceiver {
65        let (_, receiver) = &self.processes[index];
66        receiver
67    }
68
69    #[servo_tracing::instrument(skip_all)]
70    pub fn remove(&mut self, index: usize) {
71        let (mut process, _) = self.processes.swap_remove(index);
72        debug!("Removing process pid={}", process.pid());
73        // Unregister this process system memory profiler
74        self.mem_profiler_chan
75            .send(ProfilerMsg::UnregisterReporter(format!(
76                "system-content-{}",
77                process.pid()
78            )));
79        process.wait();
80    }
81}