summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-08-28 13:48:20 +0100
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-08-28 13:50:49 +0100
commit07138e1e1d3b728efdd6e8789f60c4a277a25ff7 (patch)
tree466349b3cae16eed596c34320cfee47be61a6471
parentb954640db8cd34061592c6c8865ddbeea7a3e640 (diff)
ecore exe - fig signal block to unblock again - some sys dont on exec
it seems some libc's or systes dont reset signal mask blocks on exec(). this unblocks manuaklly jus befor eexec, moves blocking to before fork and adds a "nuke all signal handlers" in the child process. fixes T8797
-rw-r--r--src/lib/ecore/ecore_exe_posix.c84
-rw-r--r--src/lib/ecore/efl_exe.c77
2 files changed, 90 insertions, 71 deletions
diff --git a/src/lib/ecore/ecore_exe_posix.c b/src/lib/ecore/ecore_exe_posix.c
index 85b7adee45..635fc0678b 100644
--- a/src/lib/ecore/ecore_exe_posix.c
+++ b/src/lib/ecore/ecore_exe_posix.c
@@ -289,56 +289,64 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
289 pid_t pid = 0; 289 pid_t pid = 0;
290 volatile int vfork_exec_errno = 0; 290 volatile int vfork_exec_errno = 0;
291 291
292 /* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */ 292 sigset_t newset, oldset;
293 /* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */ 293
294 pid = fork(); 294 sigemptyset(&newset);
295 295 sigaddset(&newset, SIGPIPE);
296 if (pid == -1) 296 sigaddset(&newset, SIGALRM);
297 { 297 sigaddset(&newset, SIGCHLD);
298 ERR("Failed to fork process"); 298 sigaddset(&newset, SIGUSR1);
299 pid = 0; 299 sigaddset(&newset, SIGUSR2);
300 } 300 sigaddset(&newset, SIGHUP);
301 else if (pid == 0) /* child */ 301 sigaddset(&newset, SIGQUIT);
302 { 302 sigaddset(&newset, SIGINT);
303 sigset_t newset; 303 sigaddset(&newset, SIGTERM);
304 304 sigaddset(&newset, SIGBUS);
305 sigemptyset(&newset); 305 sigaddset(&newset, SIGCONT);
306 sigaddset(&newset, SIGPIPE); 306 sigaddset(&newset, SIGWINCH);
307 sigaddset(&newset, SIGALRM);
308 sigaddset(&newset, SIGCHLD);
309 sigaddset(&newset, SIGUSR1);
310 sigaddset(&newset, SIGUSR2);
311 sigaddset(&newset, SIGHUP);
312 sigaddset(&newset, SIGQUIT);
313 sigaddset(&newset, SIGINT);
314 sigaddset(&newset, SIGTERM);
315 sigaddset(&newset, SIGBUS);
316 sigaddset(&newset, SIGCONT);
317 sigaddset(&newset, SIGWINCH);
318#ifdef SIGEMT 307#ifdef SIGEMT
319 sigaddset(&newset, SIGEMT); 308 sigaddset(&newset, SIGEMT);
320#endif 309#endif
321#ifdef SIGIO 310#ifdef SIGIO
322 sigaddset(&newset, SIGIO); 311 sigaddset(&newset, SIGIO);
323#endif 312#endif
324#ifdef SIGTSTP 313#ifdef SIGTSTP
325 sigaddset(&newset, SIGTSTP); 314 sigaddset(&newset, SIGTSTP);
326#endif 315#endif
327#ifdef SIGTTIN 316#ifdef SIGTTIN
328 sigaddset(&newset, SIGTTIN); 317 sigaddset(&newset, SIGTTIN);
329#endif 318#endif
330#ifdef SIGTTOU 319#ifdef SIGTTOU
331 sigaddset(&newset, SIGTTOU); 320 sigaddset(&newset, SIGTTOU);
332#endif 321#endif
333#ifdef SIGVTALRM 322#ifdef SIGVTALRM
334 sigaddset(&newset, SIGVTALRM); 323 sigaddset(&newset, SIGVTALRM);
335#endif 324#endif
336#ifdef SIGPWR 325#ifdef SIGPWR
337 sigaddset(&newset, SIGPWR); 326 sigaddset(&newset, SIGPWR);
338#endif 327#endif
339 // block all those nasty signals we don't want messing with things 328 // block all those nasty signals we don't want messing with things
340 // in signal handlers while we go from fork to exec in the child 329 // in signal handlers while we go from fork to exec in the child
341 pthread_sigmask(SIG_BLOCK, &newset, NULL); 330 pthread_sigmask(SIG_BLOCK, &newset, &oldset);
331 /* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */
332 /* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */
333 pid = fork();
334
335 if (pid == -1)
336 {
337 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
338 ERR("Failed to fork process");
339 pid = 0;
340 }
341 else if (pid == 0) /* child */
342 {
343 struct sigaction sa;
344 int sig;
345
346 sa.sa_handler = SIG_DFL;
347 sa.sa_flags = 0;
348 sigemptyset(&sa.sa_mask);
349 for (sig = 0; sig < 32; sig++) sigaction(sig, &sa, NULL);
342#ifdef HAVE_SYSTEMD 350#ifdef HAVE_SYSTEMD
343 char **env = NULL, **e; 351 char **env = NULL, **e;
344 352
@@ -439,13 +447,15 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
439 except[0] = statusPipe[1]; 447 except[0] = statusPipe[1];
440 eina_file_close_from(3, except); 448 eina_file_close_from(3, except);
441 /* Run the actual command. */ 449 /* Run the actual command. */
442 _ecore_exe_exec_it(exe_cmd, flags); /* no return */ 450 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
451 _ecore_exe_exec_it(exe_cmd, flags); /* no return */
443 } 452 }
444 } 453 }
445 _exit(-1); 454 _exit(-1);
446 } 455 }
447 else /* parent */ 456 else /* parent */
448 { 457 {
458 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
449 /* Close the unused pipes. */ 459 /* Close the unused pipes. */
450 E_NO_ERRNO(result, close(statusPipe[1]), ok); 460 E_NO_ERRNO(result, close(statusPipe[1]), ok);
451 461
diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c
index 445a3dfab2..03c52ab845 100644
--- a/src/lib/ecore/efl_exe.c
+++ b/src/lib/ecore/efl_exe.c
@@ -435,39 +435,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
435 if (loop) tdl = efl_data_scope_get(loop, EFL_TASK_CLASS); 435 if (loop) tdl = efl_data_scope_get(loop, EFL_TASK_CLASS);
436 if (pd->env) itr = efl_core_env_content_get(pd->env); 436 if (pd->env) itr = efl_core_env_content_get(pd->env);
437 if (pd->env) itr2 = efl_core_env_content_get(pd->env); 437 if (pd->env) itr2 = efl_core_env_content_get(pd->env);
438 pd->pid = fork(); 438 sigset_t newset, oldset;
439
440 if (pd->pid != 0)
441 {
442 if (itr) eina_iterator_free(itr);
443 if (itr2) eina_iterator_free(itr2);
444 // parent process is here inside this if block
445 if (td->flags & EFL_TASK_FLAGS_USE_STDIN) close(pipe_stdin[0]);
446 if (td->flags & EFL_TASK_FLAGS_USE_STDOUT) close(pipe_stdout[1]);
447 // fork failed... close up and clean and release locks
448 if (pd->pid == -1)
449 {
450 _close_fds(pd);
451 _ecore_signal_pid_unlock();
452 return EINA_FALSE;
453 }
454 // register this pid in the core sigchild/pid exit code watcher
455 _ecore_signal_pid_register(pd->pid, pd->fd.exited_write);
456 pd->exit_handler =
457 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
458 efl_loop_handler_fd_set(efl_added, pd->fd.exited_read),
459 efl_event_callback_add(efl_added,
460 EFL_LOOP_HANDLER_EVENT_READ,
461 _cb_exe_exit_read, obj),
462 efl_loop_handler_active_set(efl_added,
463 EFL_LOOP_HANDLER_FLAGS_READ));
464 _ecore_signal_pid_unlock();
465 pd->run = EINA_TRUE;
466 return EINA_TRUE;
467 }
468 // this code is in the child here, and is temporary setup until we
469 // exec() the child to replace everything.
470 sigset_t newset;
471 439
472 sigemptyset(&newset); 440 sigemptyset(&newset);
473 sigaddset(&newset, SIGPIPE); 441 sigaddset(&newset, SIGPIPE);
@@ -505,7 +473,47 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
505# endif 473# endif
506 // block all those nasty signals we don't want messing with things 474 // block all those nasty signals we don't want messing with things
507 // in signal handlers while we go from fork to exec in the child 475 // in signal handlers while we go from fork to exec in the child
508 pthread_sigmask(SIG_BLOCK, &newset, NULL); 476 pthread_sigmask(SIG_BLOCK, &newset, &oldset);
477 pd->pid = fork();
478
479 if (pd->pid != 0)
480 {
481 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
482 if (itr) eina_iterator_free(itr);
483 if (itr2) eina_iterator_free(itr2);
484 // parent process is here inside this if block
485 if (td->flags & EFL_TASK_FLAGS_USE_STDIN) close(pipe_stdin[0]);
486 if (td->flags & EFL_TASK_FLAGS_USE_STDOUT) close(pipe_stdout[1]);
487 // fork failed... close up and clean and release locks
488 if (pd->pid == -1)
489 {
490 _close_fds(pd);
491 _ecore_signal_pid_unlock();
492 return EINA_FALSE;
493 }
494 // register this pid in the core sigchild/pid exit code watcher
495 _ecore_signal_pid_register(pd->pid, pd->fd.exited_write);
496 pd->exit_handler =
497 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
498 efl_loop_handler_fd_set(efl_added, pd->fd.exited_read),
499 efl_event_callback_add(efl_added,
500 EFL_LOOP_HANDLER_EVENT_READ,
501 _cb_exe_exit_read, obj),
502 efl_loop_handler_active_set(efl_added,
503 EFL_LOOP_HANDLER_FLAGS_READ));
504 _ecore_signal_pid_unlock();
505 pd->run = EINA_TRUE;
506 return EINA_TRUE;
507 }
508 struct sigaction sa;
509 int sig;
510
511 sa.sa_handler = SIG_DFL;
512 sa.sa_flags = 0;
513 sigemptyset(&sa.sa_mask);
514 for (sig = 0; sig < 32; sig++) sigaction(sig, &sa, NULL);
515 // this code is in the child here, and is temporary setup until we
516 // exec() the child to replace everything.
509 517
510 if (td->flags & EFL_TASK_FLAGS_USE_STDIN) close(pipe_stdin[1]); 518 if (td->flags & EFL_TASK_FLAGS_USE_STDIN) close(pipe_stdin[1]);
511 if (td->flags & EFL_TASK_FLAGS_USE_STDOUT) close(pipe_stdout[0]); 519 if (td->flags & EFL_TASK_FLAGS_USE_STDOUT) close(pipe_stdout[0]);
@@ -633,6 +641,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
633 procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sig); 641 procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sig);
634 } 642 }
635# endif 643# endif
644 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
636 // actually execute! 645 // actually execute!
637 _exec(cmd, pd->flags, td->flags); 646 _exec(cmd, pd->flags, td->flags);
638 // we couldn't exec... uh oh. HAAAAAAAALP! 647 // we couldn't exec... uh oh. HAAAAAAAALP!