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 }