mz_environmentd/environmentd/
sys.rs1use anyhow::Context;
13use nix::sys::signal;
14use tracing::trace;
15
16#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "ios")))]
17pub fn adjust_rlimits() {
18 trace!("rlimit crate does not support this OS; not adjusting nofile limit");
19}
20
21#[cfg(any(target_os = "macos", target_os = "linux", target_os = "ios"))]
23pub fn adjust_rlimits() {
24 use rlimit::Resource;
25 use tracing::warn;
26
27 let (soft, hard) = match Resource::NOFILE.get() {
33 Ok(limits) => limits,
34 Err(e) => {
35 trace!("unable to read initial nofile rlimit: {}", e);
36 return;
37 }
38 };
39 trace!("initial nofile rlimit: ({}, {})", soft, hard);
40
41 #[cfg(target_os = "macos")]
42 let hard = {
43 use std::cmp;
44
45 use mz_ore::result::ResultExt;
46 use sysctl::Sysctl;
47
48 let res = sysctl::Ctl::new("kern.maxfilesperproc")
53 .and_then(|ctl| ctl.value())
54 .map_err_to_string_with_causes()
55 .and_then(|v| match v {
56 sysctl::CtlValue::Int(v) => u64::try_from(v)
57 .map_err(|_| format!("kern.maxfilesperproc unexpectedly negative: {}", v)),
58 o => Err(format!("unexpected sysctl value type: {:?}", o)),
59 });
60 match res {
61 Ok(v) => {
62 trace!("sysctl kern.maxfilesperproc hard limit: {}", v);
63 cmp::min(v, hard)
64 }
65 Err(e) => {
66 trace!("error while reading sysctl: {}", e);
67 hard
68 }
69 }
70 };
71
72 trace!("attempting to adjust nofile rlimit to ({0}, {0})", hard);
73 if let Err(e) = Resource::NOFILE.set(hard, hard) {
74 trace!("error adjusting nofile rlimit: {}", e);
75 return;
76 }
77
78 let (soft, hard) = match Resource::NOFILE.get() {
81 Ok(limits) => limits,
82 Err(e) => {
83 trace!("unable to read adjusted nofile rlimit: {}", e);
84 return;
85 }
86 };
87 trace!("adjusted nofile rlimit: ({}, {})", soft, hard);
88
89 const RECOMMENDED_SOFT: u64 = 1024;
90 if soft < RECOMMENDED_SOFT {
91 warn!(
92 "soft nofile rlimit ({}) is dangerously low; at least {} is recommended",
93 soft, RECOMMENDED_SOFT
94 )
95 }
96}
97
98pub fn enable_sigusr2_coverage_dump() -> Result<(), anyhow::Error> {
99 let action = signal::SigAction::new(
100 signal::SigHandler::Handler(handle_sigusr2_signal),
101 signal::SaFlags::SA_NODEFER | signal::SaFlags::SA_ONSTACK,
102 signal::SigSet::empty(),
103 );
104
105 unsafe { signal::sigaction(signal::SIGUSR2, &action) }
106 .context("failed to install SIGUSR2 handler")?;
107
108 Ok(())
109}
110
111pub fn enable_termination_signal_cleanup() -> Result<(), anyhow::Error> {
112 let action = signal::SigAction::new(
113 signal::SigHandler::Handler(handle_termination_signal),
114 signal::SaFlags::SA_NODEFER | signal::SaFlags::SA_ONSTACK,
115 signal::SigSet::empty(),
116 );
117
118 for signum in &[
119 signal::SIGHUP,
120 signal::SIGINT,
121 signal::SIGALRM,
122 signal::SIGTERM,
123 signal::SIGUSR1,
124 ] {
125 unsafe { signal::sigaction(*signum, &action) }
126 .with_context(|| format!("failed to install handler for {}", signum))?;
127 }
128
129 Ok(())
130}
131
132unsafe extern "C" {
133 fn __llvm_profile_write_file() -> std::ffi::c_int;
134}
135
136extern "C" fn handle_sigusr2_signal(_: i32) {
137 let _ = unsafe { __llvm_profile_write_file() };
138}
139
140extern "C" fn handle_termination_signal(signum: i32) {
141 let _ = unsafe { __llvm_profile_write_file() };
142
143 let action = signal::SigAction::new(
144 signal::SigHandler::SigDfl,
145 signal::SaFlags::SA_NODEFER | signal::SaFlags::SA_ONSTACK,
146 signal::SigSet::empty(),
147 );
148 unsafe { signal::sigaction(signum.try_into().unwrap(), &action) }
149 .unwrap_or_else(|_| panic!("failed to uninstall handler for {}", signum));
150
151 signal::raise(signum.try_into().unwrap())
152 .unwrap_or_else(|e| panic!("failed to re-raise signal {}: {}", signum, e));
153}