PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/erts/emulator/sys/unix/sys.c

https://github.com/Bwooce/otp
C | 3111 lines | 2358 code | 380 blank | 373 comment | 417 complexity | 78b994ff99679aedcbfcfe92ea0dfc8a MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-2-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * %CopyrightBegin%
  3. *
  4. * Copyright Ericsson AB 1996-2011. All Rights Reserved.
  5. *
  6. * The contents of this file are subject to the Erlang Public License,
  7. * Version 1.1, (the "License"); you may not use this file except in
  8. * compliance with the License. You should have received a copy of the
  9. * Erlang Public License along with this software. If not, it can be
  10. * retrieved online at http://www.erlang.org/.
  11. *
  12. * Software distributed under the License is distributed on an "AS IS"
  13. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  14. * the License for the specific language governing rights and limitations
  15. * under the License.
  16. *
  17. * %CopyrightEnd%
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include "config.h"
  21. #endif
  22. #ifdef ISC32
  23. #define _POSIX_SOURCE
  24. #define _XOPEN_SOURCE
  25. #endif
  26. #include <sys/times.h> /* ! */
  27. #include <time.h>
  28. #include <signal.h>
  29. #include <sys/wait.h>
  30. #include <sys/uio.h>
  31. #include <termios.h>
  32. #include <ctype.h>
  33. #include <sys/utsname.h>
  34. #ifdef ISC32
  35. #include <sys/bsdtypes.h>
  36. #endif
  37. #include <termios.h>
  38. #ifdef HAVE_FCNTL_H
  39. #include <fcntl.h>
  40. #endif
  41. #ifdef HAVE_SYS_IOCTL_H
  42. #include <sys/ioctl.h>
  43. #endif
  44. #define NEED_CHILD_SETUP_DEFINES
  45. #define ERTS_WANT_BREAK_HANDLING
  46. #define ERTS_WANT_GOT_SIGUSR1
  47. #define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */
  48. #include "sys.h"
  49. #ifdef USE_THREADS
  50. #include "erl_threads.h"
  51. #endif
  52. #include "erl_mseg.h"
  53. extern char **environ;
  54. static erts_smp_rwmtx_t environ_rwmtx;
  55. #define MAX_VSIZE 16 /* Max number of entries allowed in an I/O
  56. * vector sock_sendv().
  57. */
  58. /*
  59. * Don't need global.h, but bif_table.h (included by bif.h),
  60. * won't compile otherwise
  61. */
  62. #include "global.h"
  63. #include "bif.h"
  64. #include "erl_sys_driver.h"
  65. #include "erl_check_io.h"
  66. #include "erl_cpu_topology.h"
  67. #ifndef DISABLE_VFORK
  68. #define DISABLE_VFORK 0
  69. #endif
  70. #ifdef USE_THREADS
  71. # ifdef ENABLE_CHILD_WAITER_THREAD
  72. # define CHLDWTHR ENABLE_CHILD_WAITER_THREAD
  73. # else
  74. # define CHLDWTHR 0
  75. # endif
  76. #else
  77. # define CHLDWTHR 0
  78. #endif
  79. /*
  80. * [OTP-3906]
  81. * Solaris signal management gets confused when threads are used and a
  82. * lot of child processes dies. The confusion results in that SIGCHLD
  83. * signals aren't delivered to the emulator which in turn results in
  84. * a lot of defunct processes in the system.
  85. *
  86. * The problem seems to appear when a signal is frequently
  87. * blocked/unblocked at the same time as the signal is frequently
  88. * propagated. The child waiter thread is a workaround for this problem.
  89. * The SIGCHLD signal is always blocked (in all threads), and the child
  90. * waiter thread fetches the signal by a call to sigwait(). See
  91. * child_waiter().
  92. */
  93. typedef struct ErtsSysReportExit_ ErtsSysReportExit;
  94. struct ErtsSysReportExit_ {
  95. ErtsSysReportExit *next;
  96. Eterm port;
  97. int pid;
  98. int ifd;
  99. int ofd;
  100. #if CHLDWTHR && !defined(ERTS_SMP)
  101. int status;
  102. #endif
  103. };
  104. static ErtsSysReportExit *report_exit_list;
  105. #if CHLDWTHR && !defined(ERTS_SMP)
  106. static ErtsSysReportExit *report_exit_transit_list;
  107. #endif
  108. extern int check_async_ready(void);
  109. extern int driver_interrupt(int, int);
  110. extern void do_break(void);
  111. extern void erl_sys_args(int*, char**);
  112. /* The following two defs should probably be moved somewhere else */
  113. extern void erts_sys_init_float(void);
  114. extern void erl_crash_dump(char* file, int line, char* fmt, ...);
  115. #define DIR_SEPARATOR_CHAR '/'
  116. #if defined(DEBUG)
  117. #define ERL_BUILD_TYPE_MARKER ".debug"
  118. #elif defined(PURIFY)
  119. #define ERL_BUILD_TYPE_MARKER ".purify"
  120. #elif defined(QUANTIFY)
  121. #define ERL_BUILD_TYPE_MARKER ".quantify"
  122. #elif defined(PURECOV)
  123. #define ERL_BUILD_TYPE_MARKER ".purecov"
  124. #elif defined(VALGRIND)
  125. #define ERL_BUILD_TYPE_MARKER ".valgrind"
  126. #else /* opt */
  127. #define ERL_BUILD_TYPE_MARKER
  128. #endif
  129. #define CHILD_SETUP_PROG_NAME "child_setup" ERL_BUILD_TYPE_MARKER
  130. #if !DISABLE_VFORK
  131. static char *child_setup_prog;
  132. #endif
  133. #ifdef DEBUG
  134. static int debug_log = 0;
  135. #endif
  136. #ifdef ERTS_SMP
  137. erts_smp_atomic32_t erts_got_sigusr1;
  138. #define ERTS_SET_GOT_SIGUSR1 \
  139. erts_smp_atomic32_set(&erts_got_sigusr1, 1)
  140. #define ERTS_UNSET_GOT_SIGUSR1 \
  141. erts_smp_atomic32_set(&erts_got_sigusr1, 0)
  142. static erts_smp_atomic32_t have_prepared_crash_dump;
  143. #define ERTS_PREPARED_CRASH_DUMP \
  144. ((int) erts_smp_atomic32_xchg(&have_prepared_crash_dump, 1))
  145. #else
  146. volatile int erts_got_sigusr1;
  147. #define ERTS_SET_GOT_SIGUSR1 (erts_got_sigusr1 = 1)
  148. #define ERTS_UNSET_GOT_SIGUSR1 (erts_got_sigusr1 = 0)
  149. static volatile int have_prepared_crash_dump;
  150. #define ERTS_PREPARED_CRASH_DUMP \
  151. (have_prepared_crash_dump++)
  152. #endif
  153. static erts_smp_atomic_t sys_misc_mem_sz;
  154. #if defined(ERTS_SMP)
  155. static void smp_sig_notify(char c);
  156. static int sig_notify_fds[2] = {-1, -1};
  157. #elif defined(USE_THREADS)
  158. static int async_fd[2];
  159. #endif
  160. #if CHLDWTHR || defined(ERTS_SMP)
  161. erts_mtx_t chld_stat_mtx;
  162. #endif
  163. #if CHLDWTHR
  164. static erts_tid_t child_waiter_tid;
  165. /* chld_stat_mtx is used to protect against concurrent accesses
  166. of the driver_data fields pid, alive, and status. */
  167. erts_cnd_t chld_stat_cnd;
  168. static long children_alive;
  169. #define CHLD_STAT_LOCK erts_mtx_lock(&chld_stat_mtx)
  170. #define CHLD_STAT_UNLOCK erts_mtx_unlock(&chld_stat_mtx)
  171. #define CHLD_STAT_WAIT erts_cnd_wait(&chld_stat_cnd, &chld_stat_mtx)
  172. #define CHLD_STAT_SIGNAL erts_cnd_signal(&chld_stat_cnd)
  173. #elif defined(ERTS_SMP) /* ------------------------------------------------- */
  174. #define CHLD_STAT_LOCK erts_mtx_lock(&chld_stat_mtx)
  175. #define CHLD_STAT_UNLOCK erts_mtx_unlock(&chld_stat_mtx)
  176. #else /* ------------------------------------------------------------------- */
  177. #define CHLD_STAT_LOCK
  178. #define CHLD_STAT_UNLOCK
  179. static volatile int children_died;
  180. #endif
  181. static struct fd_data {
  182. char pbuf[4]; /* hold partial packet bytes */
  183. int psz; /* size of pbuf */
  184. char *buf;
  185. char *cpos;
  186. int sz;
  187. int remain; /* for input on fd */
  188. } *fd_data; /* indexed by fd */
  189. /* static FUNCTION(int, write_fill, (int, char*, int)); unused? */
  190. static void note_child_death(int, int);
  191. #if CHLDWTHR
  192. static void* child_waiter(void *);
  193. #endif
  194. /********************* General functions ****************************/
  195. /* This is used by both the drivers and general I/O, must be set early */
  196. static int max_files = -1;
  197. /*
  198. * a few variables used by the break handler
  199. */
  200. #ifdef ERTS_SMP
  201. erts_smp_atomic32_t erts_break_requested;
  202. #define ERTS_SET_BREAK_REQUESTED \
  203. erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 1)
  204. #define ERTS_UNSET_BREAK_REQUESTED \
  205. erts_smp_atomic32_set(&erts_break_requested, (erts_aint32_t) 0)
  206. #else
  207. volatile int erts_break_requested = 0;
  208. #define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1)
  209. #define ERTS_UNSET_BREAK_REQUESTED (erts_break_requested = 0)
  210. #endif
  211. /* set early so the break handler has access to initial mode */
  212. static struct termios initial_tty_mode;
  213. static int replace_intr = 0;
  214. /* assume yes initially, ttsl_init will clear it */
  215. int using_oldshell = 1;
  216. #ifdef ERTS_ENABLE_KERNEL_POLL
  217. int erts_use_kernel_poll = 0;
  218. struct {
  219. int (*select)(ErlDrvPort, ErlDrvEvent, int, int);
  220. int (*event)(ErlDrvPort, ErlDrvEvent, ErlDrvEventData);
  221. void (*check_io_interrupt)(int);
  222. void (*check_io_interrupt_tmd)(int, long);
  223. void (*check_io)(int);
  224. Uint (*size)(void);
  225. Eterm (*info)(void *);
  226. int (*check_io_debug)(void);
  227. } io_func = {0};
  228. int
  229. driver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on)
  230. {
  231. return (*io_func.select)(port, event, mode, on);
  232. }
  233. int
  234. driver_event(ErlDrvPort port, ErlDrvEvent event, ErlDrvEventData event_data)
  235. {
  236. return (*io_func.event)(port, event, event_data);
  237. }
  238. Eterm erts_check_io_info(void *p)
  239. {
  240. return (*io_func.info)(p);
  241. }
  242. int
  243. erts_check_io_debug(void)
  244. {
  245. return (*io_func.check_io_debug)();
  246. }
  247. static void
  248. init_check_io(void)
  249. {
  250. if (erts_use_kernel_poll) {
  251. io_func.select = driver_select_kp;
  252. io_func.event = driver_event_kp;
  253. io_func.check_io_interrupt = erts_check_io_interrupt_kp;
  254. io_func.check_io_interrupt_tmd = erts_check_io_interrupt_timed_kp;
  255. io_func.check_io = erts_check_io_kp;
  256. io_func.size = erts_check_io_size_kp;
  257. io_func.info = erts_check_io_info_kp;
  258. io_func.check_io_debug = erts_check_io_debug_kp;
  259. erts_init_check_io_kp();
  260. max_files = erts_check_io_max_files_kp();
  261. }
  262. else {
  263. io_func.select = driver_select_nkp;
  264. io_func.event = driver_event_nkp;
  265. io_func.check_io_interrupt = erts_check_io_interrupt_nkp;
  266. io_func.check_io_interrupt_tmd = erts_check_io_interrupt_timed_nkp;
  267. io_func.check_io = erts_check_io_nkp;
  268. io_func.size = erts_check_io_size_nkp;
  269. io_func.info = erts_check_io_info_nkp;
  270. io_func.check_io_debug = erts_check_io_debug_nkp;
  271. erts_init_check_io_nkp();
  272. max_files = erts_check_io_max_files_nkp();
  273. }
  274. }
  275. #define ERTS_CHK_IO_INTR (*io_func.check_io_interrupt)
  276. #define ERTS_CHK_IO_INTR_TMD (*io_func.check_io_interrupt_tmd)
  277. #define ERTS_CHK_IO (*io_func.check_io)
  278. #define ERTS_CHK_IO_SZ (*io_func.size)
  279. #else /* !ERTS_ENABLE_KERNEL_POLL */
  280. static void
  281. init_check_io(void)
  282. {
  283. erts_init_check_io();
  284. max_files = erts_check_io_max_files();
  285. }
  286. #define ERTS_CHK_IO_INTR erts_check_io_interrupt
  287. #define ERTS_CHK_IO_INTR_TMD erts_check_io_interrupt_timed
  288. #define ERTS_CHK_IO erts_check_io
  289. #define ERTS_CHK_IO_SZ erts_check_io_size
  290. #endif
  291. #ifdef ERTS_SMP
  292. void
  293. erts_sys_schedule_interrupt(int set)
  294. {
  295. ERTS_CHK_IO_INTR(set);
  296. }
  297. void
  298. erts_sys_schedule_interrupt_timed(int set, long msec)
  299. {
  300. ERTS_CHK_IO_INTR_TMD(set, msec);
  301. }
  302. #endif
  303. Uint
  304. erts_sys_misc_mem_sz(void)
  305. {
  306. Uint res = ERTS_CHK_IO_SZ();
  307. res += erts_smp_atomic_read(&sys_misc_mem_sz);
  308. return res;
  309. }
  310. /*
  311. * reset the terminal to the original settings on exit
  312. */
  313. void sys_tty_reset(int exit_code)
  314. {
  315. if (using_oldshell && !replace_intr) {
  316. SET_BLOCKING(0);
  317. }
  318. else if (isatty(0)) {
  319. tcsetattr(0,TCSANOW,&initial_tty_mode);
  320. }
  321. }
  322. #ifdef __tile__
  323. /* Direct malloc to spread memory around the caches of multiple tiles. */
  324. #include <malloc.h>
  325. MALLOC_USE_HASH(1);
  326. #endif
  327. #ifdef USE_THREADS
  328. #ifdef ERTS_THR_HAVE_SIG_FUNCS
  329. /*
  330. * Child thread inherits parents signal mask at creation. In order to
  331. * guarantee that the main thread will receive all SIGINT, SIGCHLD, and
  332. * SIGUSR1 signals sent to the process, we block these signals in the
  333. * parent thread when creating a new thread.
  334. */
  335. static sigset_t thr_create_sigmask;
  336. #endif /* #ifdef ERTS_THR_HAVE_SIG_FUNCS */
  337. typedef struct {
  338. #ifdef ERTS_THR_HAVE_SIG_FUNCS
  339. sigset_t saved_sigmask;
  340. #endif
  341. int sched_bind_data;
  342. } erts_thr_create_data_t;
  343. /*
  344. * thr_create_prepare() is called in parent thread before thread creation.
  345. * Returned value is passed as argument to thr_create_cleanup().
  346. */
  347. static void *
  348. thr_create_prepare(void)
  349. {
  350. erts_thr_create_data_t *tcdp;
  351. tcdp = erts_alloc(ERTS_ALC_T_TMP, sizeof(erts_thr_create_data_t));
  352. #ifdef ERTS_THR_HAVE_SIG_FUNCS
  353. erts_thr_sigmask(SIG_BLOCK, &thr_create_sigmask, &tcdp->saved_sigmask);
  354. #endif
  355. tcdp->sched_bind_data = erts_sched_bind_atthrcreate_prepare();
  356. return (void *) tcdp;
  357. }
  358. /* thr_create_cleanup() is called in parent thread after thread creation. */
  359. static void
  360. thr_create_cleanup(void *vtcdp)
  361. {
  362. erts_thr_create_data_t *tcdp = (erts_thr_create_data_t *) vtcdp;
  363. erts_sched_bind_atthrcreate_parent(tcdp->sched_bind_data);
  364. #ifdef ERTS_THR_HAVE_SIG_FUNCS
  365. /* Restore signalmask... */
  366. erts_thr_sigmask(SIG_SETMASK, &tcdp->saved_sigmask, NULL);
  367. #endif
  368. erts_free(ERTS_ALC_T_TMP, tcdp);
  369. }
  370. static void
  371. thr_create_prepare_child(void *vtcdp)
  372. {
  373. erts_thr_create_data_t *tcdp = (erts_thr_create_data_t *) vtcdp;
  374. #ifdef ERTS_ENABLE_LOCK_COUNT
  375. erts_lcnt_thread_setup();
  376. #endif
  377. #ifndef NO_FPE_SIGNALS
  378. /*
  379. * We do not want fp exeptions in other threads than the
  380. * scheduler threads. We enable fpe explicitly in the scheduler
  381. * threads after this.
  382. */
  383. erts_thread_disable_fpe();
  384. #endif
  385. erts_sched_bind_atthrcreate_child(tcdp->sched_bind_data);
  386. }
  387. #endif /* #ifdef USE_THREADS */
  388. void
  389. erts_sys_pre_init(void)
  390. {
  391. erts_printf_add_cr_to_stdout = 1;
  392. erts_printf_add_cr_to_stderr = 1;
  393. #ifdef USE_THREADS
  394. {
  395. erts_thr_init_data_t eid = ERTS_THR_INIT_DATA_DEF_INITER;
  396. eid.thread_create_child_func = thr_create_prepare_child;
  397. /* Before creation in parent */
  398. eid.thread_create_prepare_func = thr_create_prepare;
  399. /* After creation in parent */
  400. eid.thread_create_parent_func = thr_create_cleanup,
  401. #ifdef ERTS_THR_HAVE_SIG_FUNCS
  402. sigemptyset(&thr_create_sigmask);
  403. sigaddset(&thr_create_sigmask, SIGINT); /* block interrupt */
  404. sigaddset(&thr_create_sigmask, SIGCHLD); /* block child signals */
  405. sigaddset(&thr_create_sigmask, SIGUSR1); /* block user defined signal */
  406. #endif
  407. erts_thr_init(&eid);
  408. report_exit_list = NULL;
  409. #ifdef ERTS_ENABLE_LOCK_COUNT
  410. erts_lcnt_init();
  411. #endif
  412. #if CHLDWTHR || defined(ERTS_SMP)
  413. erts_mtx_init(&chld_stat_mtx, "child_status");
  414. #endif
  415. #if CHLDWTHR
  416. #ifndef ERTS_SMP
  417. report_exit_transit_list = NULL;
  418. #endif
  419. erts_cnd_init(&chld_stat_cnd);
  420. children_alive = 0;
  421. #endif
  422. }
  423. #ifdef ERTS_SMP
  424. erts_smp_atomic32_init(&erts_break_requested, 0);
  425. erts_smp_atomic32_init(&erts_got_sigusr1, 0);
  426. erts_smp_atomic32_init(&have_prepared_crash_dump, 0);
  427. #else
  428. erts_break_requested = 0;
  429. erts_got_sigusr1 = 0;
  430. have_prepared_crash_dump = 0;
  431. #endif
  432. #if !CHLDWTHR && !defined(ERTS_SMP)
  433. children_died = 0;
  434. #endif
  435. #endif /* USE_THREADS */
  436. erts_smp_atomic_init(&sys_misc_mem_sz, 0);
  437. }
  438. void
  439. erl_sys_init(void)
  440. {
  441. erts_smp_rwmtx_init(&environ_rwmtx, "environ");
  442. #if !DISABLE_VFORK
  443. {
  444. int res;
  445. char bindir[MAXPATHLEN];
  446. size_t bindirsz = sizeof(bindir);
  447. Uint csp_path_sz;
  448. res = erts_sys_getenv("BINDIR", bindir, &bindirsz);
  449. if (res != 0) {
  450. if (res < 0)
  451. erl_exit(-1,
  452. "Environment variable BINDIR is not set\n");
  453. if (res > 0)
  454. erl_exit(-1,
  455. "Value of environment variable BINDIR is too large\n");
  456. }
  457. if (bindir[0] != DIR_SEPARATOR_CHAR)
  458. erl_exit(-1,
  459. "Environment variable BINDIR does not contain an"
  460. " absolute path\n");
  461. csp_path_sz = (strlen(bindir)
  462. + 1 /* DIR_SEPARATOR_CHAR */
  463. + sizeof(CHILD_SETUP_PROG_NAME)
  464. + 1);
  465. child_setup_prog = erts_alloc(ERTS_ALC_T_CS_PROG_PATH, csp_path_sz);
  466. erts_smp_atomic_add(&sys_misc_mem_sz, csp_path_sz);
  467. sprintf(child_setup_prog,
  468. "%s%c%s",
  469. bindir,
  470. DIR_SEPARATOR_CHAR,
  471. CHILD_SETUP_PROG_NAME);
  472. }
  473. #endif
  474. #ifdef USE_SETLINEBUF
  475. setlinebuf(stdout);
  476. #else
  477. setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
  478. #endif
  479. erts_sys_init_float();
  480. /* we save this so the break handler can set and reset it properly */
  481. /* also so that we can reset on exit (break handler or not) */
  482. if (isatty(0)) {
  483. tcgetattr(0,&initial_tty_mode);
  484. }
  485. tzset(); /* Required at least for NetBSD with localtime_r() */
  486. }
  487. /* signal handling */
  488. #ifdef SIG_SIGSET /* Old SysV */
  489. RETSIGTYPE (*sys_sigset(sig, func))()
  490. int sig;
  491. RETSIGTYPE (*func)();
  492. {
  493. return(sigset(sig, func));
  494. }
  495. void sys_sigblock(int sig)
  496. {
  497. sighold(sig);
  498. }
  499. void sys_sigrelease(int sig)
  500. {
  501. sigrelse(sig);
  502. }
  503. #else /* !SIG_SIGSET */
  504. #ifdef SIG_SIGNAL /* Old BSD */
  505. RETSIGTYPE (*sys_sigset(sig, func))(int, int)
  506. int sig;
  507. RETSIGTYPE (*func)();
  508. {
  509. return(signal(sig, func));
  510. }
  511. sys_sigblock(int sig)
  512. {
  513. sigblock(sig);
  514. }
  515. sys_sigrelease(int sig)
  516. {
  517. sigsetmask(sigblock(0) & ~sigmask(sig));
  518. }
  519. #else /* !SIG_SIGNAL */ /* The True Way - POSIX!:-) */
  520. RETSIGTYPE (*sys_sigset(int sig, RETSIGTYPE (*func)(int)))(int)
  521. {
  522. struct sigaction act, oact;
  523. sigemptyset(&act.sa_mask);
  524. act.sa_flags = 0;
  525. act.sa_handler = func;
  526. sigaction(sig, &act, &oact);
  527. return(oact.sa_handler);
  528. }
  529. #ifdef USE_THREADS
  530. #undef sigprocmask
  531. #define sigprocmask erts_thr_sigmask
  532. #endif
  533. void sys_sigblock(int sig)
  534. {
  535. sigset_t mask;
  536. sigemptyset(&mask);
  537. sigaddset(&mask, sig);
  538. sigprocmask(SIG_BLOCK, &mask, (sigset_t *)NULL);
  539. }
  540. void sys_sigrelease(int sig)
  541. {
  542. sigset_t mask;
  543. sigemptyset(&mask);
  544. sigaddset(&mask, sig);
  545. sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)NULL);
  546. }
  547. #endif /* !SIG_SIGNAL */
  548. #endif /* !SIG_SIGSET */
  549. #if (0) /* not used? -- gordon */
  550. static void (*break_func)();
  551. static RETSIGTYPE break_handler(int sig)
  552. {
  553. #ifdef QNX
  554. /* Turn off SIGCHLD during break processing */
  555. sys_sigblock(SIGCHLD);
  556. #endif
  557. (*break_func)();
  558. #ifdef QNX
  559. sys_sigrelease(SIGCHLD);
  560. #endif
  561. }
  562. #endif /* 0 */
  563. static ERTS_INLINE void
  564. prepare_crash_dump(void)
  565. {
  566. int i, max;
  567. char env[21]; /* enough to hold any 64-bit integer */
  568. size_t envsz;
  569. if (ERTS_PREPARED_CRASH_DUMP)
  570. return; /* We have already been called */
  571. /* Make sure we unregister at epmd (unknown fd) and get at least
  572. one free filedescriptor (for erl_crash.dump) */
  573. max = max_files;
  574. if (max < 1024)
  575. max = 1024;
  576. for (i = 3; i < max; i++) {
  577. #if defined(ERTS_SMP)
  578. /* We don't want to close the signal notification pipe... */
  579. if (i == sig_notify_fds[0] || i == sig_notify_fds[1])
  580. continue;
  581. #elif defined(USE_THREADS)
  582. /* We don't want to close the async notification pipe... */
  583. if (i == async_fd[0] || i == async_fd[1])
  584. continue;
  585. #endif
  586. close(i);
  587. }
  588. envsz = sizeof(env);
  589. i = erts_sys_getenv("ERL_CRASH_DUMP_NICE", env, &envsz);
  590. if (i >= 0) {
  591. int nice_val;
  592. nice_val = i != 0 ? 0 : atoi(env);
  593. if (nice_val > 39) {
  594. nice_val = 39;
  595. }
  596. erts_silence_warn_unused_result(nice(nice_val));
  597. }
  598. envsz = sizeof(env);
  599. i = erts_sys_getenv("ERL_CRASH_DUMP_SECONDS", env, &envsz);
  600. if (i >= 0) {
  601. unsigned sec;
  602. sec = (unsigned) i != 0 ? 0 : atoi(env);
  603. alarm(sec);
  604. }
  605. }
  606. void
  607. erts_sys_prepare_crash_dump(void)
  608. {
  609. prepare_crash_dump();
  610. }
  611. static ERTS_INLINE void
  612. break_requested(void)
  613. {
  614. /*
  615. * just set a flag - checked for and handled by
  616. * scheduler threads erts_check_io() (not signal handler).
  617. */
  618. #ifdef DEBUG
  619. fprintf(stderr,"break!\n");
  620. #endif
  621. if (ERTS_BREAK_REQUESTED)
  622. erl_exit(ERTS_INTR_EXIT, "");
  623. ERTS_SET_BREAK_REQUESTED;
  624. ERTS_CHK_IO_INTR(1); /* Make sure we don't sleep in poll */
  625. }
  626. /* set up signal handlers for break and quit */
  627. #if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
  628. static RETSIGTYPE request_break(void)
  629. #else
  630. static RETSIGTYPE request_break(int signum)
  631. #endif
  632. {
  633. #ifdef ERTS_SMP
  634. smp_sig_notify('I');
  635. #else
  636. break_requested();
  637. #endif
  638. }
  639. static ERTS_INLINE void
  640. sigusr1_exit(void)
  641. {
  642. /* We do this at interrupt level, since the main reason for
  643. wanting to generate a crash dump in this way is that the emulator
  644. is hung somewhere, so it won't be able to poll any flag we set here.
  645. */
  646. ERTS_SET_GOT_SIGUSR1;
  647. prepare_crash_dump();
  648. erl_exit(1, "Received SIGUSR1\n");
  649. }
  650. #ifdef ETHR_UNUSABLE_SIGUSRX
  651. #warning "Unusable SIGUSR1 & SIGUSR2. Disabling use of these signals"
  652. #endif
  653. #ifndef ETHR_UNUSABLE_SIGUSRX
  654. #if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
  655. static RETSIGTYPE user_signal1(void)
  656. #else
  657. static RETSIGTYPE user_signal1(int signum)
  658. #endif
  659. {
  660. #ifdef ERTS_SMP
  661. smp_sig_notify('1');
  662. #else
  663. sigusr1_exit();
  664. #endif
  665. }
  666. #ifdef QUANTIFY
  667. #if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
  668. static RETSIGTYPE user_signal2(void)
  669. #else
  670. static RETSIGTYPE user_signal2(int signum)
  671. #endif
  672. {
  673. #ifdef ERTS_SMP
  674. smp_sig_notify('2');
  675. #else
  676. quantify_save_data();
  677. #endif
  678. }
  679. #endif
  680. #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
  681. static void
  682. quit_requested(void)
  683. {
  684. erl_exit(ERTS_INTR_EXIT, "");
  685. }
  686. #if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
  687. static RETSIGTYPE do_quit(void)
  688. #else
  689. static RETSIGTYPE do_quit(int signum)
  690. #endif
  691. {
  692. #ifdef ERTS_SMP
  693. smp_sig_notify('Q');
  694. #else
  695. quit_requested();
  696. #endif
  697. }
  698. /* Disable break */
  699. void erts_set_ignore_break(void) {
  700. sys_sigset(SIGINT, SIG_IGN);
  701. sys_sigset(SIGQUIT, SIG_IGN);
  702. sys_sigset(SIGTSTP, SIG_IGN);
  703. }
  704. /* Don't use ctrl-c for break handler but let it be
  705. used by the shell instead (see user_drv.erl) */
  706. void erts_replace_intr(void) {
  707. struct termios mode;
  708. if (isatty(0)) {
  709. tcgetattr(0, &mode);
  710. /* here's an example of how to replace ctrl-c with ctrl-u */
  711. /* mode.c_cc[VKILL] = 0;
  712. mode.c_cc[VINTR] = CKILL; */
  713. mode.c_cc[VINTR] = 0; /* disable ctrl-c */
  714. tcsetattr(0, TCSANOW, &mode);
  715. replace_intr = 1;
  716. }
  717. }
  718. void init_break_handler(void)
  719. {
  720. sys_sigset(SIGINT, request_break);
  721. #ifndef ETHR_UNUSABLE_SIGUSRX
  722. sys_sigset(SIGUSR1, user_signal1);
  723. #ifdef QUANTIFY
  724. sys_sigset(SIGUSR2, user_signal2);
  725. #endif
  726. #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
  727. sys_sigset(SIGQUIT, do_quit);
  728. }
  729. int sys_max_files(void)
  730. {
  731. return(max_files);
  732. }
  733. static void block_signals(void)
  734. {
  735. #if !CHLDWTHR
  736. sys_sigblock(SIGCHLD);
  737. #endif
  738. #ifndef ERTS_SMP
  739. sys_sigblock(SIGINT);
  740. #ifndef ETHR_UNUSABLE_SIGUSRX
  741. sys_sigblock(SIGUSR1);
  742. #endif
  743. #endif
  744. }
  745. static void unblock_signals(void)
  746. {
  747. /* Update erl_child_setup.c if changed */
  748. #if !CHLDWTHR
  749. sys_sigrelease(SIGCHLD);
  750. #endif
  751. #ifndef ERTS_SMP
  752. sys_sigrelease(SIGINT);
  753. #ifndef ETHR_UNUSABLE_SIGUSRX
  754. sys_sigrelease(SIGUSR1);
  755. #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
  756. #endif
  757. }
  758. /************************** Time stuff **************************/
  759. #ifdef HAVE_GETHRTIME
  760. #ifdef GETHRTIME_WITH_CLOCK_GETTIME
  761. SysHrTime sys_gethrtime(void)
  762. {
  763. struct timespec ts;
  764. long long result;
  765. if (clock_gettime(CLOCK_MONOTONIC,&ts) != 0) {
  766. erl_exit(1,"Fatal, could not get clock_monotonic value!, "
  767. "errno = %d\n", errno);
  768. }
  769. result = ((long long) ts.tv_sec) * 1000000000LL +
  770. ((long long) ts.tv_nsec);
  771. return (SysHrTime) result;
  772. }
  773. #endif
  774. #endif
  775. /************************** OS info *******************************/
  776. /* Used by erlang:info/1. */
  777. /* (This code was formerly in drv.XXX/XXX_os_drv.c) */
  778. char os_type[] = "unix";
  779. static int
  780. get_number(char **str_ptr)
  781. {
  782. char* s = *str_ptr; /* Pointer to beginning of string. */
  783. char* dot; /* Pointer to dot in string or NULL. */
  784. if (!isdigit((int) *s))
  785. return 0;
  786. if ((dot = strchr(s, '.')) == NULL) {
  787. *str_ptr = s+strlen(s);
  788. return atoi(s);
  789. } else {
  790. *dot = '\0';
  791. *str_ptr = dot+1;
  792. return atoi(s);
  793. }
  794. }
  795. void
  796. os_flavor(char* namebuf, /* Where to return the name. */
  797. unsigned size) /* Size of name buffer. */
  798. {
  799. static int called = 0;
  800. static struct utsname uts; /* Information about the system. */
  801. if (!called) {
  802. char* s;
  803. (void) uname(&uts);
  804. called = 1;
  805. for (s = uts.sysname; *s; s++) {
  806. if (isupper((int) *s)) {
  807. *s = tolower((int) *s);
  808. }
  809. }
  810. }
  811. strcpy(namebuf, uts.sysname);
  812. }
  813. void
  814. os_version(pMajor, pMinor, pBuild)
  815. int* pMajor; /* Pointer to major version. */
  816. int* pMinor; /* Pointer to minor version. */
  817. int* pBuild; /* Pointer to build number. */
  818. {
  819. struct utsname uts; /* Information about the system. */
  820. char* release; /* Pointer to the release string:
  821. * X.Y or X.Y.Z.
  822. */
  823. (void) uname(&uts);
  824. release = uts.release;
  825. *pMajor = get_number(&release);
  826. *pMinor = get_number(&release);
  827. *pBuild = get_number(&release);
  828. }
  829. void init_getenv_state(GETENV_STATE *state)
  830. {
  831. erts_smp_rwmtx_rlock(&environ_rwmtx);
  832. *state = NULL;
  833. }
  834. char *getenv_string(GETENV_STATE *state0)
  835. {
  836. char **state = (char **) *state0;
  837. char *cp;
  838. ERTS_SMP_LC_ASSERT(erts_smp_lc_rwmtx_is_rlocked(&environ_rwmtx));
  839. if (state == NULL)
  840. state = environ;
  841. cp = *state++;
  842. *state0 = (GETENV_STATE) state;
  843. return cp;
  844. }
  845. void fini_getenv_state(GETENV_STATE *state)
  846. {
  847. *state = NULL;
  848. erts_smp_rwmtx_runlock(&environ_rwmtx);
  849. }
  850. /************************** Port I/O *******************************/
  851. /* I. Common stuff */
  852. /*
  853. * Decreasing the size of it below 16384 is not allowed.
  854. */
  855. /* II. The spawn/fd/vanilla drivers */
  856. #define ERTS_SYS_READ_BUF_SZ (64*1024)
  857. /* This data is shared by these drivers - initialized by spawn_init() */
  858. static struct driver_data {
  859. int port_num, ofd, packet_bytes;
  860. ErtsSysReportExit *report_exit;
  861. int pid;
  862. int alive;
  863. int status;
  864. } *driver_data; /* indexed by fd */
  865. /* Driver interfaces */
  866. static ErlDrvData spawn_start(ErlDrvPort, char*, SysDriverOpts*);
  867. static ErlDrvData fd_start(ErlDrvPort, char*, SysDriverOpts*);
  868. static int fd_control(ErlDrvData, unsigned int, char *, int, char **, int);
  869. static ErlDrvData vanilla_start(ErlDrvPort, char*, SysDriverOpts*);
  870. static int spawn_init(void);
  871. static void fd_stop(ErlDrvData);
  872. static void stop(ErlDrvData);
  873. static void ready_input(ErlDrvData, ErlDrvEvent);
  874. static void ready_output(ErlDrvData, ErlDrvEvent);
  875. static void output(ErlDrvData, char*, int);
  876. static void outputv(ErlDrvData, ErlIOVec*);
  877. static void stop_select(ErlDrvEvent, void*);
  878. struct erl_drv_entry spawn_driver_entry = {
  879. spawn_init,
  880. spawn_start,
  881. stop,
  882. output,
  883. ready_input,
  884. ready_output,
  885. "spawn",
  886. NULL,
  887. NULL,
  888. NULL,
  889. NULL,
  890. NULL,
  891. NULL,
  892. NULL,
  893. NULL,
  894. NULL,
  895. ERL_DRV_EXTENDED_MARKER,
  896. ERL_DRV_EXTENDED_MAJOR_VERSION,
  897. ERL_DRV_EXTENDED_MINOR_VERSION,
  898. ERL_DRV_FLAG_USE_PORT_LOCKING,
  899. NULL, NULL,
  900. stop_select
  901. };
  902. struct erl_drv_entry fd_driver_entry = {
  903. NULL,
  904. fd_start,
  905. fd_stop,
  906. output,
  907. ready_input,
  908. ready_output,
  909. "fd",
  910. NULL,
  911. NULL,
  912. fd_control,
  913. NULL,
  914. outputv,
  915. NULL, /* ready_async */
  916. NULL, /* flush */
  917. NULL, /* call */
  918. NULL, /* event */
  919. ERL_DRV_EXTENDED_MARKER,
  920. ERL_DRV_EXTENDED_MAJOR_VERSION,
  921. ERL_DRV_EXTENDED_MINOR_VERSION,
  922. 0, /* ERL_DRV_FLAGs */
  923. NULL, /* handle2 */
  924. NULL, /* process_exit */
  925. stop_select
  926. };
  927. struct erl_drv_entry vanilla_driver_entry = {
  928. NULL,
  929. vanilla_start,
  930. stop,
  931. output,
  932. ready_input,
  933. ready_output,
  934. "vanilla",
  935. NULL,
  936. NULL,
  937. NULL,
  938. NULL,
  939. NULL,
  940. NULL,
  941. NULL, /* flush */
  942. NULL, /* call */
  943. NULL, /* event */
  944. ERL_DRV_EXTENDED_MARKER,
  945. ERL_DRV_EXTENDED_MAJOR_VERSION,
  946. ERL_DRV_EXTENDED_MINOR_VERSION,
  947. 0, /* ERL_DRV_FLAGs */
  948. NULL, /* handle2 */
  949. NULL, /* process_exit */
  950. stop_select
  951. };
  952. #if defined(USE_THREADS) && !defined(ERTS_SMP)
  953. static int async_drv_init(void);
  954. static ErlDrvData async_drv_start(ErlDrvPort, char*, SysDriverOpts*);
  955. static void async_drv_stop(ErlDrvData);
  956. static void async_drv_input(ErlDrvData, ErlDrvEvent);
  957. /* INTERNAL use only */
  958. struct erl_drv_entry async_driver_entry = {
  959. async_drv_init,
  960. async_drv_start,
  961. async_drv_stop,
  962. NULL,
  963. async_drv_input,
  964. NULL,
  965. "async",
  966. NULL,
  967. NULL,
  968. NULL,
  969. NULL,
  970. NULL,
  971. NULL
  972. };
  973. #endif
  974. /* Handle SIGCHLD signals. */
  975. #if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
  976. static RETSIGTYPE onchld(void)
  977. #else
  978. static RETSIGTYPE onchld(int signum)
  979. #endif
  980. {
  981. #if CHLDWTHR
  982. ASSERT(0); /* We should *never* catch a SIGCHLD signal */
  983. #elif defined(ERTS_SMP)
  984. smp_sig_notify('C');
  985. #else
  986. children_died = 1;
  987. ERTS_CHK_IO_INTR(1); /* Make sure we don't sleep in poll */
  988. #endif
  989. }
  990. static int set_driver_data(int port_num,
  991. int ifd,
  992. int ofd,
  993. int packet_bytes,
  994. int read_write,
  995. int exit_status,
  996. int pid)
  997. {
  998. ErtsSysReportExit *report_exit;
  999. if (!exit_status)
  1000. report_exit = NULL;
  1001. else {
  1002. report_exit = erts_alloc(ERTS_ALC_T_PRT_REP_EXIT,
  1003. sizeof(ErtsSysReportExit));
  1004. report_exit->next = report_exit_list;
  1005. report_exit->port = erts_port[port_num].id;
  1006. report_exit->pid = pid;
  1007. report_exit->ifd = read_write & DO_READ ? ifd : -1;
  1008. report_exit->ofd = read_write & DO_WRITE ? ofd : -1;
  1009. #if CHLDWTHR && !defined(ERTS_SMP)
  1010. report_exit->status = 0;
  1011. #endif
  1012. report_exit_list = report_exit;
  1013. }
  1014. if (read_write & DO_READ) {
  1015. driver_data[ifd].packet_bytes = packet_bytes;
  1016. driver_data[ifd].port_num = port_num;
  1017. driver_data[ifd].report_exit = report_exit;
  1018. driver_data[ifd].pid = pid;
  1019. driver_data[ifd].alive = 1;
  1020. driver_data[ifd].status = 0;
  1021. if (read_write & DO_WRITE) {
  1022. driver_data[ifd].ofd = ofd;
  1023. if (ifd != ofd)
  1024. driver_data[ofd] = driver_data[ifd]; /* structure copy */
  1025. } else { /* DO_READ only */
  1026. driver_data[ifd].ofd = -1;
  1027. }
  1028. (void) driver_select(port_num, ifd, (ERL_DRV_READ|ERL_DRV_USE), 1);
  1029. return(ifd);
  1030. } else { /* DO_WRITE only */
  1031. driver_data[ofd].packet_bytes = packet_bytes;
  1032. driver_data[ofd].port_num = port_num;
  1033. driver_data[ofd].report_exit = report_exit;
  1034. driver_data[ofd].ofd = ofd;
  1035. driver_data[ofd].pid = pid;
  1036. driver_data[ofd].alive = 1;
  1037. driver_data[ofd].status = 0;
  1038. return(ofd);
  1039. }
  1040. }
  1041. static int spawn_init()
  1042. {
  1043. int i;
  1044. #if CHLDWTHR
  1045. erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
  1046. thr_opts.detached = 0;
  1047. thr_opts.suggested_stack_size = 0; /* Smallest possible */
  1048. #endif
  1049. sys_sigset(SIGPIPE, SIG_IGN); /* Ignore - we'll handle the write failure */
  1050. driver_data = (struct driver_data *)
  1051. erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data));
  1052. erts_smp_atomic_add(&sys_misc_mem_sz,
  1053. max_files * sizeof(struct driver_data));
  1054. for (i = 0; i < max_files; i++)
  1055. driver_data[i].pid = -1;
  1056. #if CHLDWTHR
  1057. sys_sigblock(SIGCHLD);
  1058. #endif
  1059. sys_sigset(SIGCHLD, onchld); /* Reap children */
  1060. #if CHLDWTHR
  1061. erts_thr_create(&child_waiter_tid, child_waiter, NULL, &thr_opts);
  1062. #endif
  1063. return 1;
  1064. }
  1065. static void close_pipes(int ifd[2], int ofd[2], int read_write)
  1066. {
  1067. if (read_write & DO_READ) {
  1068. (void) close(ifd[0]);
  1069. (void) close(ifd[1]);
  1070. }
  1071. if (read_write & DO_WRITE) {
  1072. (void) close(ofd[0]);
  1073. (void) close(ofd[1]);
  1074. }
  1075. }
  1076. static void init_fd_data(int fd, int prt)
  1077. {
  1078. fd_data[fd].buf = NULL;
  1079. fd_data[fd].cpos = NULL;
  1080. fd_data[fd].remain = 0;
  1081. fd_data[fd].sz = 0;
  1082. fd_data[fd].psz = 0;
  1083. }
  1084. static char **build_unix_environment(char *block)
  1085. {
  1086. int i;
  1087. int j;
  1088. int len;
  1089. char *cp;
  1090. char **cpp;
  1091. char** old_env;
  1092. ERTS_SMP_LC_ASSERT(erts_smp_lc_rwmtx_is_rlocked(&environ_rwmtx));
  1093. cp = block;
  1094. len = 0;
  1095. while (*cp != '\0') {
  1096. cp += strlen(cp) + 1;
  1097. len++;
  1098. }
  1099. old_env = environ;
  1100. while (*old_env++ != NULL) {
  1101. len++;
  1102. }
  1103. cpp = (char **) erts_alloc_fnf(ERTS_ALC_T_ENVIRONMENT,
  1104. sizeof(char *) * (len+1));
  1105. if (cpp == NULL) {
  1106. return NULL;
  1107. }
  1108. cp = block;
  1109. len = 0;
  1110. while (*cp != '\0') {
  1111. cpp[len] = cp;
  1112. cp += strlen(cp) + 1;
  1113. len++;
  1114. }
  1115. i = len;
  1116. for (old_env = environ; *old_env; old_env++) {
  1117. char* old = *old_env;
  1118. for (j = 0; j < len; j++) {
  1119. char *s, *t;
  1120. s = cpp[j];
  1121. t = old;
  1122. while (*s == *t && *s != '=') {
  1123. s++, t++;
  1124. }
  1125. if (*s == '=' && *t == '=') {
  1126. break;
  1127. }
  1128. }
  1129. if (j == len) { /* New version not found */
  1130. cpp[len++] = old;
  1131. }
  1132. }
  1133. for (j = 0; j < i; ) {
  1134. size_t last = strlen(cpp[j])-1;
  1135. if (cpp[j][last] == '=' && strchr(cpp[j], '=') == cpp[j]+last) {
  1136. cpp[j] = cpp[--len];
  1137. if (len < i) {
  1138. i--;
  1139. } else {
  1140. j++;
  1141. }
  1142. }
  1143. else {
  1144. j++;
  1145. }
  1146. }
  1147. cpp[len] = NULL;
  1148. return cpp;
  1149. }
  1150. /*
  1151. [arndt] In most Unix systems, including Solaris 2.5, 'fork' allocates memory
  1152. in swap space for the child of a 'fork', whereas 'vfork' does not do this.
  1153. The natural call to use here is therefore 'vfork'. Due to a bug in
  1154. 'vfork' in Solaris 2.5 (apparently fixed in 2.6), using 'vfork'
  1155. can be dangerous in what seems to be these circumstances:
  1156. If the child code under a vfork sets the signal action to SIG_DFL
  1157. (or SIG_IGN)
  1158. for any signal which was previously set to a signal handler, the
  1159. state of the parent is clobbered, so that the later arrival of
  1160. such a signal yields a sigsegv in the parent. If the signal was
  1161. not set to a signal handler, but ignored, all seems to work.
  1162. If you change the forking code below, beware of this.
  1163. */
  1164. static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)
  1165. {
  1166. #define CMD_LINE_PREFIX_STR "exec "
  1167. #define CMD_LINE_PREFIX_STR_SZ (sizeof(CMD_LINE_PREFIX_STR) - 1)
  1168. int ifd[2], ofd[2], len, pid, i;
  1169. char **volatile new_environ; /* volatile since a vfork() then cannot
  1170. cause 'new_environ' to be clobbered
  1171. in the parent process. */
  1172. int saved_errno;
  1173. long res;
  1174. char *cmd_line;
  1175. #ifndef QNX
  1176. int unbind;
  1177. #endif
  1178. #if !DISABLE_VFORK
  1179. int no_vfork;
  1180. size_t no_vfork_sz = sizeof(no_vfork);
  1181. no_vfork = (erts_sys_getenv("ERL_NO_VFORK",
  1182. (char *) &no_vfork,
  1183. &no_vfork_sz) >= 0);
  1184. #endif
  1185. switch (opts->read_write) {
  1186. case DO_READ:
  1187. if (pipe(ifd) < 0)
  1188. return ERL_DRV_ERROR_ERRNO;
  1189. if (ifd[0] >= max_files) {
  1190. close_pipes(ifd, ofd, opts->read_write);
  1191. errno = EMFILE;
  1192. return ERL_DRV_ERROR_ERRNO;
  1193. }
  1194. ofd[1] = -1; /* keep purify happy */
  1195. break;
  1196. case DO_WRITE:
  1197. if (pipe(ofd) < 0) return ERL_DRV_ERROR_ERRNO;
  1198. if (ofd[1] >= max_files) {
  1199. close_pipes(ifd, ofd, opts->read_write);
  1200. errno = EMFILE;
  1201. return ERL_DRV_ERROR_ERRNO;
  1202. }
  1203. ifd[0] = -1; /* keep purify happy */
  1204. break;
  1205. case DO_READ|DO_WRITE:
  1206. if (pipe(ifd) < 0) return ERL_DRV_ERROR_ERRNO;
  1207. errno = EMFILE; /* default for next two conditions */
  1208. if (ifd[0] >= max_files || pipe(ofd) < 0) {
  1209. close_pipes(ifd, ofd, DO_READ);
  1210. return ERL_DRV_ERROR_ERRNO;
  1211. }
  1212. if (ofd[1] >= max_files) {
  1213. close_pipes(ifd, ofd, opts->read_write);
  1214. errno = EMFILE;
  1215. return ERL_DRV_ERROR_ERRNO;
  1216. }
  1217. break;
  1218. default:
  1219. ASSERT(0);
  1220. return ERL_DRV_ERROR_GENERAL;
  1221. }
  1222. if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
  1223. /* started with spawn_executable, not with spawn */
  1224. len = strlen(name);
  1225. cmd_line = (char *) erts_alloc_fnf(ERTS_ALC_T_TMP, len + 1);
  1226. if (!cmd_line) {
  1227. close_pipes(ifd, ofd, opts->read_write);
  1228. errno = ENOMEM;
  1229. return ERL_DRV_ERROR_ERRNO;
  1230. }
  1231. memcpy((void *) cmd_line,(void *) name, len);
  1232. cmd_line[len] = '\0';
  1233. if (access(cmd_line,X_OK) != 0) {
  1234. int save_errno = errno;
  1235. erts_free(ERTS_ALC_T_TMP, cmd_line);
  1236. errno = save_errno;
  1237. return ERL_DRV_ERROR_ERRNO;
  1238. }
  1239. } else {
  1240. /* make the string suitable for giving to "sh" */
  1241. len = strlen(name);
  1242. cmd_line = (char *) erts_alloc_fnf(ERTS_ALC_T_TMP,
  1243. CMD_LINE_PREFIX_STR_SZ + len + 1);
  1244. if (!cmd_line) {
  1245. close_pipes(ifd, ofd, opts->read_write);
  1246. errno = ENOMEM;
  1247. return ERL_DRV_ERROR_ERRNO;
  1248. }
  1249. memcpy((void *) cmd_line,
  1250. (void *) CMD_LINE_PREFIX_STR,
  1251. CMD_LINE_PREFIX_STR_SZ);
  1252. memcpy((void *) (cmd_line + CMD_LINE_PREFIX_STR_SZ), (void *) name, len);
  1253. cmd_line[CMD_LINE_PREFIX_STR_SZ + len] = '\0';
  1254. }
  1255. erts_smp_rwmtx_rlock(&environ_rwmtx);
  1256. if (opts->envir == NULL) {
  1257. new_environ = environ;
  1258. } else if ((new_environ = build_unix_environment(opts->envir)) == NULL) {
  1259. erts_smp_rwmtx_runlock(&environ_rwmtx);
  1260. erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
  1261. errno = ENOMEM;
  1262. return ERL_DRV_ERROR_ERRNO;
  1263. }
  1264. #ifndef QNX
  1265. /* Block child from SIGINT and SIGUSR1. Must be before fork()
  1266. to be safe. */
  1267. block_signals();
  1268. CHLD_STAT_LOCK;
  1269. unbind = erts_sched_bind_atfork_prepare();
  1270. #if !DISABLE_VFORK
  1271. /* See fork/vfork discussion before this function. */
  1272. if (no_vfork) {
  1273. #endif
  1274. DEBUGF(("Using fork\n"));
  1275. pid = fork();
  1276. if (pid == 0) {
  1277. /* The child! Setup child... */
  1278. if (erts_sched_bind_atfork_child(unbind) != 0)
  1279. goto child_error;
  1280. /* OBSERVE!
  1281. * Keep child setup after vfork() (implemented below and in
  1282. * erl_child_setup.c) up to date if changes are made here.
  1283. */
  1284. if (opts->use_stdio) {
  1285. if (opts->read_write & DO_READ) {
  1286. /* stdout for process */
  1287. if (dup2(ifd[1], 1) < 0)
  1288. goto child_error;
  1289. if(opts->redir_stderr)
  1290. /* stderr for process */
  1291. if (dup2(ifd[1], 2) < 0)
  1292. goto child_error;
  1293. }
  1294. if (opts->read_write & DO_WRITE)
  1295. /* stdin for process */
  1296. if (dup2(ofd[0], 0) < 0)
  1297. goto child_error;
  1298. }
  1299. else { /* XXX will fail if ofd[0] == 4 (unlikely..) */
  1300. if (opts->read_write & DO_READ)
  1301. if (dup2(ifd[1], 4) < 0)
  1302. goto child_error;
  1303. if (opts->read_write & DO_WRITE)
  1304. if (dup2(ofd[0], 3) < 0)
  1305. goto child_error;
  1306. }
  1307. for (i = opts->use_stdio ? 3 : 5; i < max_files; i++)
  1308. (void) close(i);
  1309. if (opts->wd && chdir(opts->wd) < 0)
  1310. goto child_error;
  1311. #if defined(USE_SETPGRP_NOARGS) /* SysV */
  1312. (void) setpgrp();
  1313. #elif defined(USE_SETPGRP) /* BSD */
  1314. (void) setpgrp(0, getpid());
  1315. #else /* POSIX */
  1316. (void) setsid();
  1317. #endif
  1318. unblock_signals();
  1319. if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
  1320. if (opts->argv == NULL) {
  1321. execle(cmd_line,cmd_line,(char *) NULL, new_environ);
  1322. } else {
  1323. if (opts->argv[0] == erts_default_arg0) {
  1324. opts->argv[0] = cmd_line;
  1325. }
  1326. execve(cmd_line, opts->argv, new_environ);
  1327. if (opts->argv[0] == cmd_line) {
  1328. opts->argv[0] = erts_default_arg0;
  1329. }
  1330. }
  1331. } else {
  1332. execle("/bin/sh", "sh", "-c", cmd_line, (char *) NULL, new_environ);
  1333. }
  1334. child_error:
  1335. _exit(1);
  1336. }
  1337. #if !DISABLE_VFORK
  1338. }
  1339. else { /* Use vfork() */
  1340. char **cs_argv= erts_alloc(ERTS_ALC_T_TMP,(CS_ARGV_NO_OF_ARGS + 1)*
  1341. sizeof(char *));
  1342. char fd_close_range[44]; /* 44 bytes are enough to */
  1343. char dup2_op[CS_ARGV_NO_OF_DUP2_OPS][44]; /* hold any "%d:%d" string */
  1344. /* on a 64-bit machine. */
  1345. /* Setup argv[] for the child setup program (implemented in
  1346. erl_child_setup.c) */
  1347. i = 0;
  1348. if (opts->use_stdio) {
  1349. if (opts->read_write & DO_READ){
  1350. /* stdout for process */
  1351. sprintf(&dup2_op[i++][0], "%d:%d", ifd[1], 1);
  1352. if(opts->redir_stderr)
  1353. /* stderr for process */
  1354. sprintf(&dup2_op[i++][0], "%d:%d", ifd[1], 2);
  1355. }
  1356. if (opts->read_write & DO_WRITE)
  1357. /* stdin for process */
  1358. sprintf(&dup2_op[i++][0], "%d:%d", ofd[0], 0);
  1359. } else { /* XXX will fail if ofd[0] == 4 (unlikely..) */
  1360. if (opts->read_write & DO_READ)
  1361. sprintf(&dup2_op[i++][0], "%d:%d", ifd[1], 4);
  1362. if (opts->read_write & DO_WRITE)
  1363. sprintf(&dup2_op[i++][0], "%d:%d", ofd[0], 3);
  1364. }
  1365. for (; i < CS_ARGV_NO_OF_DUP2_OPS; i++)
  1366. strcpy(&dup2_op[i][0], "-");
  1367. sprintf(fd_close_range, "%d:%d", opts->use_stdio ? 3 : 5, max_files-1);
  1368. cs_argv[CS_ARGV_PROGNAME_IX] = child_setup_prog;
  1369. cs_argv[CS_ARGV_WD_IX] = opts->wd ? opts->wd : ".";
  1370. cs_argv[CS_ARGV_UNBIND_IX] = erts_sched_bind_atvfork_child(unbind);
  1371. cs_argv[CS_ARGV_FD_CR_IX] = fd_close_range;
  1372. for (i = 0; i < CS_ARGV_NO_OF_DUP2_OPS; i++)
  1373. cs_argv[CS_ARGV_DUP2_OP_IX(i)] = &dup2_op[i][0];
  1374. if (opts->spawn_type == ERTS_SPAWN_EXECUTABLE) {
  1375. int num = 0;
  1376. int j = 0;
  1377. if (opts->argv != NULL) {
  1378. for(; opts->argv[num] != NULL; ++num)
  1379. ;
  1380. }
  1381. cs_argv = erts_realloc(ERTS_ALC_T_TMP,cs_argv, (CS_ARGV_NO_OF_ARGS + 1 + num + 1) * sizeof(char *));
  1382. cs_argv[CS_ARGV_CMD_IX] = "-";
  1383. cs_argv[CS_ARGV_NO_OF_ARGS] = cmd_line;
  1384. if (opts->argv != NULL) {
  1385. for (;opts->argv[j] != NULL; ++j) {
  1386. if (opts->argv[j] == erts_default_arg0) {
  1387. cs_argv[CS_ARGV_NO_OF_ARGS + 1 + j] = cmd_line;
  1388. } else {
  1389. cs_argv[CS_ARGV_NO_OF_ARGS + 1 + j] = opts->argv[j];
  1390. }
  1391. }
  1392. }
  1393. cs_argv[CS_ARGV_NO_OF_ARGS + 1 + j] = NULL;
  1394. } else {
  1395. cs_argv[CS_ARGV_CMD_IX] = cmd_line; /* Command */
  1396. cs_argv[CS_ARGV_NO_OF_ARGS] = NULL;
  1397. }
  1398. DEBUGF(("Using vfork\n"));
  1399. pid = vfork();
  1400. if (pid == 0) {
  1401. /* The child! */
  1402. /* Observe!
  1403. * OTP-4389: The child setup program (implemented in
  1404. * erl_child_setup.c) will perform the necessary setup of the
  1405. * child before it execs to the user program. This because
  1406. * vfork() only allow an *immediate* execve() or _exit() in the
  1407. * child.
  1408. */
  1409. execve(child_setup_prog, cs_argv, new_environ);
  1410. _exit(1);
  1411. }
  1412. erts_free(ERTS_ALC_T_TMP,cs_argv);
  1413. }
  1414. #endif
  1415. erts_sched_bind_atfork_parent(unbind);
  1416. if (pid == -1) {
  1417. saved_errno = errno;
  1418. CHLD_STAT_UNLOCK;
  1419. erts_smp_rwmtx_runlock(&environ_rwmtx);
  1420. erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
  1421. unblock_signals();
  1422. close_pipes(ifd, ofd, opts->read_write);
  1423. errno = saved_errno;
  1424. return ERL_DRV_ERROR_ERRNO;
  1425. }
  1426. #else /* QNX */
  1427. if (opts->use_stdio) {
  1428. if (opts->read_write & DO_READ)
  1429. qnx_spawn_options.iov[1] = ifd[1]; /* stdout for process */
  1430. if (opts->read_write & DO_WRITE)
  1431. qnx_spawn_options.iov[0] = ofd[0]; /* stdin for process */
  1432. }
  1433. else {
  1434. if (opts->read_write & DO_READ)
  1435. qnx_spawn_options.iov[4] = ifd[1];
  1436. if (opts->read_write & DO_WRITE)
  1437. qnx_spawn_options.iov[3] = ofd[0];
  1438. }
  1439. /* Close fds on exec */
  1440. for (i = 3; i < max_files; i++)
  1441. fcntl(i, F_SETFD, 1);
  1442. qnx_spawn_options.flags = _SPAWN_SETSID;
  1443. if ((pid = spawnl(P_NOWAIT, "/bin/sh", "/bin/sh", "-c", cmd_line,
  1444. (char *) 0)) < 0) {
  1445. erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
  1446. reset_qnx_spawn();
  1447. erts_smp_rwmtx_runlock(&environ_rwmtx);
  1448. close_pipes(ifd, ofd, opts->read_write);
  1449. return ERL_DRV_ERROR_GENERAL;
  1450. }
  1451. reset_qnx_spawn();
  1452. #endif /* QNX */
  1453. erts_free(ERTS_ALC_T_TMP, (void *) cmd_line);
  1454. if (new_environ != environ)
  1455. erts_free(ERTS_ALC_T_ENVIRONMENT, (void *) new_environ);
  1456. if (opts->read_write & DO_READ)
  1457. (void) close(ifd[1]);
  1458. if (opts->read_write & DO_WRITE)
  1459. (void) close(ofd[0]);
  1460. if (opts->read_write & DO_READ) {
  1461. SET_NONBLOCKING(ifd[0]);
  1462. init_fd_data(ifd[0], port_num);
  1463. }
  1464. if (opts->read_write & DO_WRITE) {
  1465. SET_NONBLOCKING(ofd[1]);
  1466. init_fd_data(ofd[1], port_num);
  1467. }
  1468. res = set_driver_data(port_num, ifd[0], ofd[1], opts->packet_bytes,
  1469. opts->read_write, opts->exit_status, pid);
  1470. /* Don't unblock SIGCHLD until now, since the call above must
  1471. first complete putting away the info about our new subprocess. */
  1472. unblock_signals();
  1473. #if CHLDWTHR
  1474. ASSERT(children_alive >= 0);
  1475. if (!(children_alive++))
  1476. CHLD_STAT_SIGNAL; /* Wake up child waiter thread if no children
  1477. was alive before we fork()ed ... */
  1478. #endif
  1479. /* Don't unlock chld_stat_mtx until now of the same reason as above */
  1480. CHLD_STAT_UNLOCK;
  1481. erts_smp_rwmtx_runlock(&environ_rwmtx);
  1482. return (ErlDrvData)res;
  1483. #undef CMD_LINE_PREFIX_STR
  1484. #undef CMD_LINE_PREFIX_STR_SZ
  1485. }
  1486. #ifdef QNX
  1487. static reset_qnx_spawn()
  1488. {
  1489. int i;
  1490. /* Reset qnx_spawn_options */
  1491. qnx_spawn_options.flags = 0;
  1492. qnx_spawn_options.iov[0] = 0xff;
  1493. qnx_spawn_options.iov[1] = 0xff;
  1494. qnx_spawn_options.iov[2] = 0xff;
  1495. qnx_spawn_options.iov[3] = 0xff;
  1496. }
  1497. #endif
  1498. #define FD_DEF_HEIGHT 24
  1499. #define FD_DEF_WIDTH 80
  1500. /* Control op */
  1501. #define FD_CTRL_OP_GET_WINSIZE 100
  1502. static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height)
  1503. {
  1504. #ifdef TIOCGWINSZ
  1505. struct winsize ws;
  1506. if (ioctl(fd,TIOCGWINSZ,&ws) == 0) {
  1507. *width = (Uint32) ws.ws_col;
  1508. *height = (Uint32) ws.ws_row;
  1509. return 0;
  1510. }
  1511. #endif
  1512. return -1;
  1513. }
  1514. static int fd_control(ErlDrvData drv_data,
  1515. unsigned int command,
  1516. char *buf, int len,
  1517. char **rbuf, int rlen)
  1518. {
  1519. int fd = (int)(long)drv_data;
  1520. char resbuff[2*sizeof(Uint32)];
  1521. switch (command) {
  1522. case FD_CTRL_OP_GET_WINSIZE:
  1523. {
  1524. Uint32 w,h;
  1525. if (fd_get_window_size(fd,&w,&h))
  1526. return 0;
  1527. memcpy(resbuff,&w,sizeof(Uint32));
  1528. memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32));
  1529. }
  1530. break;
  1531. default:
  1532. return 0;
  1533. }
  1534. if (rlen < 2*sizeof(Uint32)) {
  1535. *rbuf = driver_alloc(2*sizeof(Uint32));
  1536. }
  1537. memcpy(*rbuf,resbuff,2*sizeof(Uint32));
  1538. return 2*sizeof(Uint32);
  1539. }
  1540. static ErlDrvData fd_start(ErlDrvPort port_num, char* name,
  1541. SysDriverOpts* opts)
  1542. {
  1543. ErlDrvData res;
  1544. if (((opts->read_write & DO_READ) && opts->ifd >= max_files) ||
  1545. ((opts->read_write & DO_WRITE) && opts->ofd >= max_files))
  1546. return ERL_DRV_ERROR_GENERAL;
  1547. /*
  1548. * Historical:
  1549. *
  1550. * "Note about nonblocking I/O.
  1551. *
  1552. * At least on Solaris, setting the write end of a TTY to nonblocking,
  1553. * will set the input end to nonblocking as well (and vice-versa).
  1554. * If erl is run in a pipeline like this: cat | erl
  1555. * the input end of the TTY will be the standard input of cat.
  1556. * And cat is not prepared to handle nonblocking I/O."
  1557. *
  1558. * Actually, the reason for this is not that the tty itself gets set
  1559. * in non-blocking mode, but that the "input end" (cat's stdin) and
  1560. * the "output end" (erlang's stdout) are typically the "same" file
  1561. * descriptor, dup()'ed from a single fd by one of this process'
  1562. * ancestors.
  1563. *
  1564. * The workaround for this problem used to be a rather bad kludge,
  1565. * interposing an extra process ("internal cat") between erlang's
  1566. * stdout and the original stdout, allowing erlang to set its stdout
  1567. * in non-blocking mode without affecting the stdin of the preceding
  1568. * process in the pipeline - and being a kludge, it caused all kinds
  1569. * of weird problems.
  1570. *
  1571. * So, this is the current logic:
  1572. *
  1573. * The only reason to set non-blocking mode on the output fd at all is
  1574. * if it's something that can cause a write() to block, of course,
  1575. * i.e. primarily if it points to a tty, socket, pipe, or fifo.
  1576. *
  1577. * If we don't set non-blocking mode when we "should" have, and output
  1578. * becomes blocked, the entire runtime system will be suspended - this
  1579. * is normally bad of course, and can happen fairly "easily" - e.g. user
  1580. * hits ^S on tty - but doesn't necessarily happen.
  1581. *
  1582. * If we do set non-blocking mode when we "shouldn't" have, the runtime
  1583. * system will end up seeing EOF on the input fd (due to the preceding
  1584. * process dying), which typically will cause the entire runtime system
  1585. * to terminate immediately (due to whatever erlang process is seeing
  1586. * the EOF taking it as a signal to halt the system). This is *very* bad.
  1587. *
  1588. * I.e. we should take a conservative approach, and only set non-
  1589. * blocking mode when we a) need to, and b) are reasonably certain
  1590. * that it won't be a problem. And as in the example above, the problem
  1591. * occurs when input fd and output fd point to different "things".
  1592. *
  1593. * However, determining that they are not just the same "type" of
  1594. * "thing", but actually the same instance of that type of thing, is
  1595. * unreasonably complex in many/most cases.
  1596. *
  1597. * Also, with pipes, sockets, and fifos it's far from obvious that the
  1598. * user *wants* non-blocking output: If you're running erlang inside
  1599. * some complex pipeline, you're probably not running a real-time system
  1600. * that must never stop, but rather *want* it to suspend if the output
  1601. * channel is "full".
  1602. *
  1603. * So, the bottom line: We will only set the output fd non-blocking if
  1604. * it points to a tty, and either a) the input fd also points to a tty,
  1605. * or b) we can make sure that setting the output fd non-blocking
  1606. * doesn't interfere with someone else's input, via a somewhat milder
  1607. * kludge than the above.
  1608. *
  1609. * Also keep in mind that while this code is almost exclusively run as
  1610. * a result of an erlang open_port({fd,0,1}, ...), that isn't the only
  1611. * case - it can be called with any old pre-existing file descriptors,
  1612. * the relations between which (if they're even two) we can only guess
  1613. * at - still, we try our best...
  1614. */
  1615. if (opts->read_write & DO_READ) {
  1616. init_fd_data(opts->ifd, port_num);
  1617. }
  1618. if (opts->read_write & DO_WRITE) {
  1619. init_fd_data(opts->ofd, port_num);
  1620. /* If we don't have a read end, all bets are off - no non-blocking. */
  1621. if (opts->read_write & DO_READ) {
  1622. if (isatty(opts->ofd)) { /* output fd is a tty:-) */
  1623. if (isatty(opts->ifd)) { /* input fd is also a tty */
  1624. /* To really do this "right", we should also check that
  1625. input and output fd point to the *same* tty - but
  1626. this seems like overkill; ttyname() isn't for free,
  1627. and this is a very common case - and it's hard to
  1628. imagine a scenario where setting non-blocking mode
  1629. here would cause problems - go ahead and do it. */
  1630. SET_NONBLOCKING(opts->ofd);
  1631. } else { /* output fd is a tty, input fd isn't */
  1632. /* This is a "problem case", but also common (see the
  1633. example above) - i.e. it makes sense to try a bit
  1634. harder before giving up on non-blocking mode: Try to
  1635. re-open the tty that the output fd points to, and if
  1636. successful replace the original one with the "new" fd
  1637. obtained this way, and set *that* one in non-blocking
  1638. mode. (Yes, this is a kludge.)
  1639. However, re-opening the tty may fail in a couple of
  1640. (unusual) cases:
  1641. 1) The name of the tty (or an equivalent one, i.e.
  1642. same major/minor number) can't be found, because
  1643. it actually lives somewhere other than /dev (or
  1644. wherever ttyname() looks for it), and isn't
  1645. equivalent to any of those that do live in the
  1646. "standard" place - this should be *very* unusual.
  1647. 2) Permissions on the tty don't allow us to open it -
  1648. it's perfectly possible to have an fd open to an
  1649. object whose permissions wouldn't allow us to open
  1650. it. This is not as unusual as it sounds, one case
  1651. is if the user has su'ed to someone else (not
  1652. root) - we have a read/write fd open to the tty
  1653. (because it has been inherited all the way down
  1654. here), but we have neither read nor write
  1655. permission for the tty.
  1656. In these cases, we finally give up, and don't set the
  1657. output fd in non-blocking mode. */
  1658. char *tty;
  1659. int nfd;
  1660. if ((tty = ttyname(opts->ofd)) != NULL &&
  1661. (nfd = open(tty, O_WRONLY)) != -1) {
  1662. dup2(nfd, opts->ofd);
  1663. close(nfd);
  1664. SET_NONBLOCKING(opts->ofd);
  1665. }
  1666. }
  1667. }
  1668. }
  1669. }
  1670. CHLD_STAT_LOCK;
  1671. res = (ErlDrvData)(long)set_driver_data(port_num, opts->ifd, opts->ofd,
  1672. opts->packet_bytes,
  1673. opts->read_write, 0, -1);
  1674. CHLD_STAT_UNLOCK;
  1675. return res;
  1676. }
  1677. static void clear_fd_data(int fd)
  1678. {
  1679. if (fd_data[fd].sz > 0) {
  1680. erts_free(ERTS_ALC_T_FD_ENTRY_BUF, (void *) fd_data[fd].buf);
  1681. ASSERT(erts_smp_atomic_read(&sys_misc_mem_sz) >= fd_data[fd].sz);
  1682. erts_smp_atomic_add(&sys_misc_mem_sz, -1

Large files files are truncated, but you can click here to view the full file