Skip to content

Commit 06dcdea

Browse files
committed
Use prlimit for linux gnu
1 parent 9fd823d commit 06dcdea

File tree

2 files changed

+67
-44
lines changed

2 files changed

+67
-44
lines changed

src/sys/resource.rs

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -131,29 +131,42 @@ cfg_if! {
131131
///
132132
/// [`Resource`]: enum.Resource.html
133133
pub fn getrlimit(resource: Resource) -> Result<(Option<rlim_t>, Option<rlim_t>)> {
134-
let mut rlim = mem::MaybeUninit::<rlimit>::uninit();
135-
136-
#[cfg(all(target_os = "linux", target_env = "gnu"))]
137-
let res =
138-
unsafe { libc::getrlimit(resource as __rlimit_resource_t, rlim.as_mut_ptr() as *mut _) };
139-
#[cfg(any(
140-
target_os = "freebsd",
141-
target_os = "openbsd",
142-
target_os = "netbsd",
143-
target_os = "macos",
144-
target_os = "ios",
145-
target_os = "android",
146-
target_os = "dragonfly",
147-
target_os = "bitrig",
148-
target_os = "linux", // target_env != "gnu"
149-
))]
150-
let res = unsafe { libc::getrlimit(resource as c_int, rlim.as_mut_ptr() as *mut _) };
134+
let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();
135+
136+
cfg_if! {
137+
if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
138+
// the below implementation is mimicing the similar implementation in golang
139+
// https://go-review.googlesource.com/c/sys/+/230478/2/unix/syscall_linux_arm64.go#176
140+
// seems for some of the architectures, we prefer to use prlimit instead of {g,s}etrlimit
141+
142+
let res = unsafe { libc::prlimit(0, resource as __rlimit_resource_t, std::ptr::null(), old_rlim.as_mut_ptr() as *mut _) };
143+
if res == -1 {
144+
// when error happens, the map will return an Err, the (None, None) is just make compiler
145+
// happy, it will not go through
146+
return Errno::result(res).map(|_|{ (None, None) });
147+
}
148+
let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr() as *mut _) };
149+
150+
}else if #[cfg(any(
151+
target_os = "freebsd",
152+
target_os = "openbsd",
153+
target_os = "netbsd",
154+
target_os = "macos",
155+
target_os = "ios",
156+
target_os = "android",
157+
target_os = "dragonfly",
158+
target_os = "bitrig",
159+
target_os = "linux", // target_env != "gnu"
160+
))]{
161+
let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr() as *mut _) };
162+
}
163+
}
151164

152-
let rlim = unsafe { rlim.assume_init() };
165+
let old_rlim = unsafe { old_rlim.assume_init() };
153166
Errno::result(res).map(|_| {
154167
(
155-
Some(rlim.rlim_cur).filter(|x| *x != RLIM_INFINITY),
156-
Some(rlim.rlim_max).filter(|x| *x != RLIM_INFINITY),
168+
Some(old_rlim.rlim_cur).filter(|x| *x != RLIM_INFINITY),
169+
Some(old_rlim.rlim_max).filter(|x| *x != RLIM_INFINITY),
157170
)
158171
})
159172
}
@@ -191,23 +204,36 @@ pub fn setrlimit(
191204
soft_limit: Option<rlim_t>,
192205
hard_limit: Option<rlim_t>,
193206
) -> Result<()> {
194-
let mut rlim = unsafe { mem::MaybeUninit::<rlimit>::uninit().assume_init() };
195-
rlim.rlim_cur = soft_limit.unwrap_or(RLIM_INFINITY);
196-
rlim.rlim_max = hard_limit.unwrap_or(RLIM_INFINITY);
207+
let mut new_rlim = unsafe { mem::MaybeUninit::<rlimit>::uninit().assume_init() };
208+
new_rlim.rlim_cur = soft_limit.unwrap_or(RLIM_INFINITY);
209+
new_rlim.rlim_max = hard_limit.unwrap_or(RLIM_INFINITY);
210+
211+
cfg_if! {
212+
if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
213+
// the below implementation is mimicing the similar implementation in golang
214+
// https://go-review.googlesource.com/c/sys/+/230478/2/unix/syscall_linux_arm64.go#176
215+
// seems for some of the architectures, we prefer to use prlimit instead of {g,s}etrlimit
216+
let res = unsafe { libc::prlimit(0, resource as __rlimit_resource_t, &new_rlim as *const _, std::ptr::null_mut()) };
217+
if res == -1 {
218+
return Errno::result(res).map(|_| ());
219+
}
220+
221+
let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const _) };
222+
223+
}else if #[cfg(any(
224+
target_os = "freebsd",
225+
target_os = "openbsd",
226+
target_os = "netbsd",
227+
target_os = "macos",
228+
target_os = "ios",
229+
target_os = "android",
230+
target_os = "dragonfly",
231+
target_os = "bitrig",
232+
target_os = "linux", // target_env != "gnu"
233+
))]{
234+
let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const _) };
235+
}
236+
}
197237

198-
#[cfg(all(target_os = "linux", target_env = "gnu"))]
199-
let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &rlim as *const _) };
200-
#[cfg(any(
201-
target_os = "freebsd",
202-
target_os = "openbsd",
203-
target_os = "netbsd",
204-
target_os = "macos",
205-
target_os = "ios",
206-
target_os = "android",
207-
target_os = "dragonfly",
208-
target_os = "bitrig",
209-
target_os = "linux", // target_env != "gnu"
210-
))]
211-
let res = unsafe { libc::setrlimit(resource as c_int, &rlim as *const _) };
212238
Errno::result(res).map(|_| ())
213239
}

test/test_resource.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ pub fn test_resource_limits_nofile() {
3333
pub fn test_resource_limits_stack() {
3434
let (mut soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_STACK).unwrap();
3535
let orig_limit = (soft_limit, hard_limit);
36-
37-
soft_limit = hard_limit.or(Some(10000));
36+
eprintln!("\n{:?} --- {:?}", soft_limit, hard_limit);
37+
soft_limit = Some(4194304);
3838
setrlimit(Resource::RLIMIT_STACK, soft_limit, hard_limit).unwrap();
3939

4040
let limit2 = getrlimit(Resource::RLIMIT_STACK).unwrap();
41+
eprintln!("\n{:?} --- {:?}", limit2.0, limit2.1);
42+
4143
assert_eq!(soft_limit, limit2.0);
4244
assert_eq!(hard_limit, limit2.1);
4345

@@ -46,9 +48,4 @@ pub fn test_resource_limits_stack() {
4648
let final_limit = getrlimit(Resource::RLIMIT_STACK).unwrap();
4749
assert_eq!(orig_limit.0, final_limit.0);
4850
assert_eq!(orig_limit.1, final_limit.1);
49-
50-
// assert_eq!(
51-
// format!("softlimit-{:?}, hardlimit-{:?}, limit2.0-{:?}, limit2.1-{:?}, final_limit.0-{:?}, final_limit.0-{:?}"
52-
// , soft_limit, hard_limit, limit2.0, limit2.1, final_limit.0, final_limit.1),
53-
// "");
5451
}

0 commit comments

Comments
 (0)