@@ -63,6 +63,81 @@ pub fn run_in_newsched_task_core(f: ~fn()) {
63
63
sched. bootstrap ( task) ;
64
64
}
65
65
66
+ #[ cfg( target_os="macos" ) ]
67
+ #[ allow( non_camel_case_types) ]
68
+ mod darwin_fd_limit {
69
+ /*!
70
+ * darwin_fd_limit exists to work around an issue where launchctl on Mac OS X defaults the
71
+ * rlimit maxfiles to 256/unlimited. The default soft limit of 256 ends up being far too low
72
+ * for our multithreaded scheduler testing, depending on the number of cores available.
73
+ *
74
+ * This fixes issue #7772.
75
+ */
76
+
77
+ use libc;
78
+ type rlim_t = libc:: uint64_t ;
79
+ struct rlimit {
80
+ rlim_cur : rlim_t ,
81
+ rlim_max : rlim_t
82
+ }
83
+ #[ nolink]
84
+ extern {
85
+ // name probably doesn't need to be mut, but the C function doesn't specify const
86
+ fn sysctl ( name : * mut libc:: c_int , namelen : libc:: c_uint ,
87
+ oldp : * mut libc:: c_void , oldlenp : * mut libc:: size_t ,
88
+ newp : * mut libc:: c_void , newlen : libc:: size_t ) -> libc:: c_int ;
89
+ fn getrlimit ( resource : libc:: c_int , rlp : * mut rlimit ) -> libc:: c_int ;
90
+ fn setrlimit ( resource : libc:: c_int , rlp : * rlimit ) -> libc:: c_int ;
91
+ }
92
+ static CTL_KERN : libc:: c_int = 1 ;
93
+ static KERN_MAXFILESPERPROC : libc:: c_int = 29 ;
94
+ static RLIMIT_NOFILE : libc:: c_int = 8 ;
95
+
96
+ pub unsafe fn raise_fd_limit ( ) {
97
+ // The strategy here is to fetch the current resource limits, read the kern.maxfilesperproc
98
+ // sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value.
99
+ use ptr:: { to_unsafe_ptr, to_mut_unsafe_ptr, mut_null} ;
100
+ use sys:: size_of_val;
101
+ use os:: last_os_error;
102
+
103
+ // Fetch the kern.maxfilesperproc value
104
+ let mut mib: [ libc:: c_int , ..2 ] = [ CTL_KERN , KERN_MAXFILESPERPROC ] ;
105
+ let mut maxfiles: libc:: c_int = 0 ;
106
+ let mut size: libc:: size_t = size_of_val ( & maxfiles) as libc:: size_t ;
107
+ if sysctl ( to_mut_unsafe_ptr ( & mut mib[ 0 ] ) , 2 ,
108
+ to_mut_unsafe_ptr ( & mut maxfiles) as * mut libc:: c_void ,
109
+ to_mut_unsafe_ptr ( & mut size) ,
110
+ mut_null ( ) , 0 ) != 0 {
111
+ let err = last_os_error ( ) ;
112
+ error ! ( "raise_fd_limit: error calling sysctl: %s" , err) ;
113
+ return ;
114
+ }
115
+
116
+ // Fetch the current resource limits
117
+ let mut rlim = rlimit { rlim_cur : 0 , rlim_max : 0 } ;
118
+ if getrlimit ( RLIMIT_NOFILE , to_mut_unsafe_ptr ( & mut rlim) ) != 0 {
119
+ let err = last_os_error ( ) ;
120
+ error ! ( "raise_fd_limit: error calling getrlimit: %s" , err) ;
121
+ return ;
122
+ }
123
+
124
+ // Bump the soft limit to the smaller of kern.maxfilesperproc and the hard limit
125
+ rlim. rlim_cur = :: cmp:: min ( maxfiles as rlim_t , rlim. rlim_max ) ;
126
+
127
+ // Set our newly-increased resource limit
128
+ if setrlimit ( RLIMIT_NOFILE , to_unsafe_ptr ( & rlim) ) != 0 {
129
+ let err = last_os_error ( ) ;
130
+ error ! ( "raise_fd_limit: error calling setrlimit: %s" , err) ;
131
+ return ;
132
+ }
133
+ }
134
+ }
135
+
136
+ #[ cfg( not( target_os="macos" ) ) ]
137
+ mod darwin_fd_limit {
138
+ pub unsafe fn raise_fd_limit ( ) { }
139
+ }
140
+
66
141
/// Create more than one scheduler and run a function in a task
67
142
/// in one of the schedulers. The schedulers will stay alive
68
143
/// until the function `f` returns.
@@ -72,6 +147,9 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
72
147
use rt:: sched:: Shutdown ;
73
148
use rt:: util;
74
149
150
+ // Bump the fd limit on OS X. See darwin_fd_limit for an explanation.
151
+ unsafe { darwin_fd_limit:: raise_fd_limit ( ) }
152
+
75
153
let f = Cell :: new ( f) ;
76
154
77
155
do run_in_bare_thread {
0 commit comments