1 #if defined(__APPLE__) && defined(__MACH__) && !defined(OS_X) 2 # define OS_X 3 #endif 4 5 #include "rktio_platform.h" 6 7 #ifdef RKTIO_SYSTEM_WINDOWS 8 # include <winsock2.h> 9 # include <windows.h> 10 #endif 11 #ifdef RKTIO_USE_PTHREADS 12 # include <pthread.h> 13 #endif 14 #ifdef RKTIO_USE_XLOCALE 15 # ifdef RKTIO_USE_XLOCALE_HEADER 16 # include <xlocale.h> 17 # else 18 # include <locale.h> 19 # endif 20 #endif 21 22 #if defined(RKTIO_SYSTEM_UNIX) && !defined(RKTIO_STATIC_FDSET_SIZE) 23 # define USE_DYNAMIC_FDSET_SIZE 24 #endif 25 26 #ifdef RKTIO_SYSTEM_WINDOWS 27 # define USE_FAR_RKTIO_FDCALLS 28 #endif 29 #ifdef USE_DYNAMIC_FDSET_SIZE 30 # define USE_FAR_RKTIO_FDCALLS 31 #endif 32 #ifdef HAVE_POLL_SYSCALL 33 # define USE_FAR_RKTIO_FDCALLS 34 #endif 35 36 #if defined(RKTIO_SYSTEM_UNIX) && defined(RKTIO_USE_PTHREADS) 37 # define SUPPORT_BACKGROUND_SLEEP_THREAD 38 struct background_sleep_t; 39 #endif 40 41 /*========================================================================*/ 42 /* File-descriptor actions without a rktio_t */ 43 /*========================================================================*/ 44 45 intptr_t rktio_internal_fd_system_fd(rktio_fd_t *rfd); 46 rktio_ok_t rktio_internal_close(rktio_t *rktio /* may be NULL */, rktio_fd_t *rfd, int set_error); 47 48 /*========================================================================*/ 49 /* Globals, as gathered into `rktio_t` */ 50 /*========================================================================*/ 51 52 struct rktio_t { 53 int errid; 54 int errkind; 55 int errstep; 56 #ifdef RKTIO_SYSTEM_WINDOWS 57 char *last_err_str; 58 #endif 59 60 #ifdef RKTIO_SYSTEM_UNIX 61 struct group_member_cache_entry_t *group_member_cache; 62 int external_event_fd; 63 int put_external_event_fd; 64 int long_term_poll_set_fd; 65 #endif 66 #ifdef RKTIO_SYSTEM_WINDOWS 67 int windows_nt_or_later; 68 HANDLE break_semaphore; 69 int wsr_size; 70 struct rktio_socket_t *wsr_array; 71 int made_progress; 72 DWORD max_sleep_time; 73 int got_hires_freq; 74 LARGE_INTEGER hires_freq; 75 #endif 76 #ifdef USE_FAR_RKTIO_FDCALLS 77 /* A single fdset that can be reused for immediate actions: */ 78 struct rktio_poll_set_t *rktio_global_poll_set; 79 #endif 80 #ifdef RKTIO_GROWABLE_FDSET 81 int max_fd_so_far; 82 #endif 83 84 #if defined(RKTIO_SYSTEM_WINDOWS) || defined(RKTIO_USE_PTHREADS) 85 int ghbn_started, ghbn_run; 86 struct rktio_addrinfo_lookup_t *ghbn_requests; 87 # ifdef RKTIO_USE_PTHREADS 88 pthread_t ghbn_th; 89 pthread_mutex_t ghbn_lock; 90 pthread_cond_t ghbn_start; 91 # endif 92 # ifdef RKTIO_SYSTEM_WINDOWS 93 HANDLE ghbn_th; 94 HANDLE ghbn_lock; 95 HANDLE ghbn_start; 96 # endif 97 #endif 98 99 #if defined(RKTIO_SYSTEM_UNIX) && !defined(RKTIO_USE_PTHREADS) 100 struct System_Child *system_children; 101 volatile int need_to_check_children; 102 int in_sigchld_chain; 103 struct rktio_t *next; /* chaining for SIGCHLD handling */ 104 #endif 105 #ifdef RKTIO_SYSTEM_WINDOWS 106 uintptr_t process_children_msecs; 107 HANDLE process_job_object; 108 #endif 109 110 #ifdef HAVE_INOTIFY_SYSCALL 111 struct rin_inotify_state_t *inotify_server; 112 #endif 113 114 #ifdef RKTIO_SYSTEM_WINDOWS 115 intptr_t wide_buffer_size; 116 wchar_t *wide_buffer; 117 #endif 118 119 #ifdef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS 120 struct rktio_hash_t *locked_fd_process_map; 121 #endif 122 123 #ifdef RKTIO_SYSTEM_WINDOWS 124 HANDLE hEventLog; 125 #endif 126 127 int pending_os_signals[RKTIO_NUM_OS_SIGNALS]; 128 129 int processor_count; 130 131 struct rktio_dll_t *all_dlls; 132 struct rktio_hash_t *dlls_by_name; 133 #ifdef RKTIO_SYSTEM_UNIX 134 char *dll_error; 135 #endif 136 137 #ifdef SUPPORT_BACKGROUND_SLEEP_THREAD 138 struct background_sleep_t *background; 139 #endif 140 141 #ifdef OS_X 142 int macos_kernel_version; /* e.g., 10 => 10.6, 15 => 10.11 */ 143 #endif 144 145 #ifdef RKTIO_USE_XLOCALE 146 locale_t locale; 147 #endif 148 }; 149 150 /*========================================================================*/ 151 /* Poll sets */ 152 /*========================================================================*/ 153 154 void rktio_alloc_global_poll_set(rktio_t *rktio); 155 void rktio_free_global_poll_set(rktio_t *rktio); 156 int rktio_initialize_signal(rktio_t *rktio); 157 void rktio_free_signal(rktio_t *rktio); 158 159 #ifdef USE_FAR_RKTIO_FDCALLS 160 161 rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos); 162 void rktio_fdzero(rktio_poll_set_t *fd); 163 void rktio_fdset(rktio_poll_set_t *fd, intptr_t n); 164 void rktio_fdclr(rktio_poll_set_t *fd, intptr_t n); 165 int rktio_fdisset(rktio_poll_set_t *fd, intptr_t n); 166 167 # define DECL_FDSET(n, c) rktio_poll_set_t *n 168 # define INIT_DECL_FDSET(r, w, e) { \ 169 r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 0 ); \ 170 w = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 1 ); \ 171 e = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 2 ); \ 172 } 173 # define INIT_DECL_RD_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 0 ) 174 # define INIT_DECL_WR_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 1 ) 175 # define INIT_DECL_ER_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 2 ) 176 177 # define RKTIO_GET_FDSET(p, n) rktio_get_fdset(p, n) 178 # define RKTIO_FD_ZERO(p) rktio_fdzero(p) 179 # define RKTIO_FD_SET(n, p) rktio_fdset(p, n) 180 # define RKTIO_FD_CLR(n, p) rktio_fdclr(p, n) 181 # define RKTIO_FD_ISSET(n, p) rktio_fdisset(p, n) 182 183 # if !defined(HAVE_POLL_SYSCALL) && !defined(RKTIO_SYSTEM_WINDOWS) 184 # ifdef RKTIO_GROWABLE_FDSET 185 # define RKTIO_FDS(p) ((fd_set *)rktio_resolve_fds(p)) 186 void *rktio_resolve_fds(rktio_poll_set_t *fd); 187 # else 188 # define RKTIO_FDS(p) ((fd_set *)p) 189 # endif 190 # endif 191 192 #else 193 194 #include <sys/select.h> 195 struct rktio_poll_set_t { fd_set data; int nosleep; }; 196 197 /* Need "far" call to fdzero to deal with `nosleep`: */ 198 void rktio_fdzero(rktio_poll_set_t *fd); 199 200 # define DECL_FDSET(n, c) rktio_poll_set_t n[c] 201 # define INIT_DECL_FDSET(r, w, e) /* empty */ 202 # define INIT_DECL_RD_FDSET(r) /* empty */ 203 # define INIT_DECL_WR_FDSET(r) /* empty */ 204 # define INIT_DECL_ER_FDSET(r) /* empty */ 205 206 # define RKTIO_FDS(p) (&(p)->data) 207 208 # define RKTIO_GET_FDSET(p, n) ((p)+(n)) 209 # define RKTIO_FD_ZERO(p) rktio_fdzero(p) 210 # define RKTIO_FD_SET(n, p) FD_SET(n, RKTIO_FDS(p)) 211 # define RKTIO_FD_CLR(n, p) FD_CLR(n, RKTIO_FDS(p)) 212 # define RKTIO_FD_ISSET(n, p) FD_ISSET(n, RKTIO_FDS(p)) 213 214 #endif 215 216 void rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds); 217 void rktio_clean_fd_set(rktio_poll_set_t *fds); 218 int rktio_get_fd_limit(rktio_poll_set_t *fds); 219 220 #if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL) 221 int rktio_ltps_get_fd(rktio_ltps_t *lt); 222 #else 223 rktio_poll_set_t *rktio_ltps_get_fd_set(rktio_ltps_t *lt); 224 #endif 225 226 #if defined(HAVE_POLL_SYSCALL) 227 int rktio_get_poll_count(rktio_poll_set_t *fds); 228 struct pollfd *rktio_get_poll_fd_array(rktio_poll_set_t *fds); 229 #endif 230 231 /*========================================================================*/ 232 /* Network */ 233 /*========================================================================*/ 234 235 void rktio_socket_init(rktio_t *rktio, rktio_fd_t *rfd); 236 237 int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd, int set_error); 238 void rktio_socket_own(rktio_t *rktio, rktio_fd_t *rfd); 239 void rktio_socket_forget_owned(rktio_t *rktio, rktio_fd_t *rfd); 240 rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd); 241 242 int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd); 243 int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd); 244 245 intptr_t rktio_socket_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr_t len); 246 intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len); 247 248 void rktio_free_ghbn(rktio_t *rktio); 249 250 const char *rktio_gai_strerror(rktio_t *rktio, int errnum); 251 252 /*========================================================================*/ 253 /* Processes */ 254 /*========================================================================*/ 255 256 int rktio_process_init(rktio_t *rktio); 257 void rktio_process_deinit(rktio_t *rktio); 258 259 /*========================================================================*/ 260 /* Strings */ 261 /*========================================================================*/ 262 263 #ifdef RKTIO_SYSTEM_WINDOWS 264 # define MSC_IZE(n) _ ## n 265 # define MSC_W_IZE(n) _w ## n 266 # define MSC_WIDE_PATH_temp(n) WIDE_PATH_temp(n) 267 #else 268 # define MSC_IZE(n) n 269 # define MSC_W_IZE(n) MSC_IZE(n) 270 # define MSC_WIDE_PATH_temp(n) n 271 #endif 272 273 #ifdef RKTIO_SYSTEM_WINDOWS 274 275 wchar_t *rktio_convert_to_wchar(rktio_t *rktio, const char *s, int do_copy); 276 char *rktio_convert_from_wchar(const wchar_t *ws, int free_given); 277 278 # define WIDE_PATH_temp(s) rktio_convert_to_wchar(rktio, s, 0) 279 # define WIDE_PATH_copy(s) rktio_convert_to_wchar(rktio, s, 1) 280 281 # define NARROW_PATH_copy(ws) rktio_convert_from_wchar(ws, 0) 282 # define NARROW_PATH_copy_then_free(ws) rktio_convert_from_wchar(ws, 1) 283 284 typedef wchar_t WIDE_PATH_t; 285 286 #else 287 288 typedef char WIDE_PATH_t; 289 290 #endif 291 292 void rktio_convert_init(rktio_t *rktio); 293 void rktio_convert_deinit(rktio_t *rktio); 294 295 /*========================================================================*/ 296 /* Hash table */ 297 /*========================================================================*/ 298 299 /* Maps keys that aren't -1 to non-NULL values */ 300 301 typedef struct rktio_hash_t rktio_hash_t; 302 303 rktio_hash_t *rktio_hash_new(void); 304 void rktio_hash_free(rktio_hash_t *ht, int free_values); 305 int rktio_hash_is_empty(rktio_hash_t *ht); 306 void *rktio_hash_get(rktio_hash_t *ht, intptr_t key); 307 void rktio_hash_remove(rktio_hash_t *ht, intptr_t key, int dont_rehash); 308 void rktio_hash_set(rktio_hash_t *ht, intptr_t key, void *v); 309 310 intptr_t rktio_hash_size(rktio_hash_t *ht); 311 intptr_t rktio_hash_get_key(rktio_hash_t *ht, intptr_t i); 312 313 intptr_t rktio_hash_string(const char *s); 314 315 /*========================================================================*/ 316 /* Misc */ 317 /*========================================================================*/ 318 319 /* On Mac OS, for example, `read` and `write` expect a value less than 320 2GB. Use 32MB as a limit that is very large, but still likely small 321 enough for all OSes. */ 322 #define MAX_READ_WRITE_REQUEST_BYTES (32 * 1048576) 323 #define LIMIT_REQUEST_SIZE(n) (((n) > MAX_READ_WRITE_REQUEST_BYTES) ? MAX_READ_WRITE_REQUEST_BYTES : (n)) 324 325 void rktio_get_posix_error(rktio_t *rktio); 326 #define get_posix_error() rktio_get_posix_error(rktio) 327 328 void rktio_set_racket_error(rktio_t *rktio, int errid); 329 #define set_racket_error(e) rktio_set_racket_error(rktio, e) 330 331 #ifdef RKTIO_SYSTEM_WINDOWS 332 void rktio_get_windows_error(rktio_t *rktio); 333 # define get_windows_error() rktio_get_windows_error(rktio) 334 void rktio_set_windows_error(rktio_t *rktio, int errid); 335 # define set_windows_error(errid) rktio_set_windows_error(rktio, errid) 336 #endif 337 338 void rktio_error_clean(rktio_t *rktio); 339 340 void rktio_dll_clean(rktio_t *rktio); 341 #ifdef RKTIO_SYSTEM_WINDOWS 342 HANDLE rktio_load_library(rktio_const_string_t name); 343 void *rktio_get_proc_address(HANDLE m, rktio_const_string_t name); 344 #endif 345 346 #if defined(USE_FNDELAY_O_NONBLOCK) 347 # define RKTIO_NONBLOCKING FNDELAY 348 #else 349 # define RKTIO_NONBLOCKING O_NONBLOCK 350 #endif 351 352 #ifndef RKTIO_BINARY 353 # define RKTIO_BINARY 0 354 #endif 355 356 #ifdef RKTIO_SYSTEM_UNIX 357 int rktio_reliably_close_err(intptr_t s); 358 void rktio_reliably_close(intptr_t s); 359 int rktio_close_fds_len(); 360 void rktio_close_fds_after_fork(int len, int skip1, int skip2, int skip3); 361 #endif 362 363 int rktio_system_fd_is_terminal(rktio_t *rktio, intptr_t fd); 364 365 #if defined(RKTIO_USE_PTHREADS) && !defined(NO_PTHREAD_CANCEL) 366 # define RKTIO_USE_PENDING_OPEN 367 #endif 368 369 #ifdef RKTIO_USE_PENDING_OPEN 370 struct open_in_thread_t; 371 rktio_fd_t *rktio_pending_system_fd(rktio_t *rktio, struct open_in_thread_t *oit, int modes); 372 void rktio_update_system_fd(rktio_t *rktio, rktio_fd_t *rfd, int fd, int modes); 373 int rktio_fd_is_pending_open(rktio_t *rktio, rktio_fd_t *rfd); 374 int rktio_pending_open_poll(rktio_t *rktio, rktio_fd_t *rfd, struct open_in_thread_t *oit); 375 void rktio_poll_add_pending_open(rktio_t *rktio, rktio_fd_t *rfd, struct open_in_thread_t *oit, rktio_poll_set_t *fds); 376 void rktio_pending_open_detach(rktio_t *rktio, struct open_in_thread_t *oit); 377 void rktio_pending_open_attach(rktio_t *rktio, struct open_in_thread_t *oit); 378 void rktio_pending_open_retain(rktio_t *rktio, struct open_in_thread_t *oit); 379 int rktio_pending_open_release(rktio_t *rktio, struct open_in_thread_t *oit); 380 #endif 381 382 void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars); 383 384 void rktio_stop_fs_change(rktio_t *rktio); 385 386 void rktio_init_time(rktio_t *rktio); 387 388 void rktio_init_cpu(rktio_t *rktio); 389 390 #ifdef RKTIO_SYSTEM_WINDOWS 391 int rktio_winsock_init(rktio_t *rktio); 392 void rktio_winsock_done(rktio_t *rktio); 393 #endif 394 void rktio_init_wide(rktio_t *rktio); 395 396 #ifdef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS 397 void rktio_release_lockf(rktio_t *rktio, int fd); 398 #endif 399 400 int rktio_make_os_pipe(rktio_t *rktio, intptr_t *a, int flags); 401 402 #ifdef RKTIO_SYSTEM_UNIX 403 char **rktio_get_environ_array(void); 404 #endif 405 406 void rktio_syslog_init(rktio_t* rktio); 407 void rktio_syslog_clean(rktio_t* rktio); 408 409 void rktio_stop_background(rktio_t *rktio); 410 411 #ifdef USE_TRANSITIONAL_64_FILE_OPS 412 # define BIG_OFF_T_IZE(n) n ## 64 413 #else 414 # define BIG_OFF_T_IZE(n) n 415 #endif 416 417 char *rktio_strndup(char *s, intptr_t len); 418 419 #ifdef RKTIO_SYSTEM_UNIX 420 void rktio_set_signal_handler(int sig_id, void (*proc)(int)); 421 void rktio_restore_modified_signal_handlers(); 422 #endif 423 void rktio_forget_os_signal_handler(rktio_t *rktio); 424 425 426 #ifdef RKTIO_SYSTEM_WINDOWS 427 int rktio_system_time_is_dst(SYSTEMTIME *st, TIME_ZONE_INFORMATION *_tz); 428 #endif 429 430 #ifdef RKTIO_SYSTEM_WINDOWS 431 void rktio_console_ctl_c(void); 432 void rktio_set_console_handler(void); 433 #endif 434