git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

src/server/process.rs (2.2K)

 1 // SPDX-FileCopyrightText: © 2022 The River Developers
 2 // SPDX-License-Identifier: GPL-3.0-only
 3 
 4 use std::sync::Mutex;
 5 use nix::sys::resource::{getrlimit, setrlimit, Resource};
 6 
 7 static ORIGINAL_RLIMIT: Mutex<Option<libc::rlimit>> = Mutex::new(None);
 8 
 9 pub fn setup() {
10     // Ignore SIGPIPE so we don't get killed when writing to a socket that
11     // has had its read end closed by another process.
12     unsafe {
13         libc::signal(libc::SIGPIPE, libc::SIG_IGN);
14     }
15 
16     // Most unix systems have a default limit of 1024 file descriptors.
17     // Raise it to avoid issues with many wayland clients.
18     if let Ok((cur, max)) = getrlimit(Resource::RLIMIT_NOFILE) {
19         let mut orig = ORIGINAL_RLIMIT.lock().unwrap();
20         *orig = Some(libc::rlimit {
21             rlim_cur: cur,
22             rlim_max: max,
23         });
24 
25         // A compositor's legitimate fd usage scales with clients × buffers
26         // (every imported dmabuf holds one), and hitting the ceiling turns
27         // accept() into an EMFILE spin that takes the session down — 4096
28         // proved reachable under client-reconnect churn. Children get the
29         // original limit back via cleanup_child.
30         let new_cur = std::cmp::min(65536, max);
31         if let Err(e) = setrlimit(Resource::RLIMIT_NOFILE, new_cur, max) {
32             log::error!("setrlimit failed: {}, using system default limit of {}", e, cur);
33         } else {
34             log::info!("raised file descriptor limit of the river process to {}", new_cur);
35         }
36     } else {
37         log::error!("getrlimit failed, using system default file descriptor limit");
38     }
39 }
40 
41 pub fn cleanup_child() {
42     unsafe {
43         if libc::setsid() < 0 {
44             // setsid failed
45         }
46 
47         let mut empty_mask: libc::sigset_t = std::mem::zeroed();
48         libc::sigemptyset(&mut empty_mask);
49         libc::sigprocmask(libc::SIG_SETMASK, &empty_mask, std::ptr::null_mut());
50 
51         libc::signal(libc::SIGPIPE, libc::SIG_DFL);
52         libc::signal(libc::SIGCHLD, libc::SIG_DFL);
53     }
54 
55     let orig = ORIGINAL_RLIMIT.lock().unwrap();
56     if let Some(original) = *orig {
57         unsafe {
58             libc::setrlimit(libc::RLIMIT_NOFILE, &original);
59         }
60     }
61 }