@@ -131,29 +131,42 @@ cfg_if! {
131
131
///
132
132
/// [`Resource`]: enum.Resource.html
133
133
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
+ }
151
164
152
- let rlim = unsafe { rlim . assume_init ( ) } ;
165
+ let old_rlim = unsafe { old_rlim . assume_init ( ) } ;
153
166
Errno :: result ( res) . map ( |_| {
154
167
(
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 ) ,
157
170
)
158
171
} )
159
172
}
@@ -191,23 +204,36 @@ pub fn setrlimit(
191
204
soft_limit : Option < rlim_t > ,
192
205
hard_limit : Option < rlim_t > ,
193
206
) -> 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
+ }
197
237
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 _ ) } ;
212
238
Errno :: result ( res) . map ( |_| ( ) )
213
239
}
0 commit comments