summaryrefslogtreecommitdiff
path: root/src/lib/ecore
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-08-14 15:22:17 +0100
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-08-20 08:52:32 +0100
commit4b4c208d99358941cfe886bc1a87e38c2390f0bd (patch)
tree07f1aa535981c3da041b5cea6d25a2fcf2023b9a /src/lib/ecore
parentcef058c48b21c6effed8d6580876632b4344ec7f (diff)
ecore - don't do anything with heap between fork and exec
this avoids a possibgle deadlock if a malloc impl is holding a lock and has not released it at the time we fork. @fix
Diffstat (limited to 'src/lib/ecore')
-rw-r--r--src/lib/ecore/ecore_exe_posix.c31
-rw-r--r--src/lib/ecore/efl_exe.c79
2 files changed, 84 insertions, 26 deletions
diff --git a/src/lib/ecore/ecore_exe_posix.c b/src/lib/ecore/ecore_exe_posix.c
index f88f0ca15b..895875c8c3 100644
--- a/src/lib/ecore/ecore_exe_posix.c
+++ b/src/lib/ecore/ecore_exe_posix.c
@@ -218,6 +218,13 @@ _impl_ecore_exe_run_priority_get(void)
218 return run_pri; 218 return run_pri;
219} 219}
220 220
221#if defined (__FreeBSD__) || defined (__OpenBSD__)
222# include <dlfcn.h>
223static char ***_dl_environ;
224#else
225extern char **environ;
226#endif
227
221Eo * 228Eo *
222_impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe) 229_impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
223{ 230{
@@ -294,7 +301,29 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
294 else if (pid == 0) /* child */ 301 else if (pid == 0) /* child */
295 { 302 {
296#ifdef HAVE_SYSTEMD 303#ifdef HAVE_SYSTEMD
297 unsetenv("NOTIFY_SOCKET"); 304 char **env = NULL, **e;
305
306# if defined (__FreeBSD__) || defined (__OpenBSD__)
307 _dl_environ = dlsym(NULL, "environ");
308 env = *_dl_environ;
309# else
310 env = environ;
311# endif
312 // find NOTIFY_SOCKET env var and remove it without any heap work
313 if (env)
314 {
315 Eina_Bool shuffle = EINA_FALSE;
316
317 for (e = env; *e; e++)
318 {
319 if (!shuffle)
320 {
321 if (!strncmp(e[0], "NOTIFY_SOCKET=", 14))
322 shuffle = EINA_TRUE;
323 }
324 if (shuffle) e[0] = e[1];
325 }
326 }
298#endif 327#endif
299 if (run_pri != ECORE_EXE_PRIORITY_INHERIT) 328 if (run_pri != ECORE_EXE_PRIORITY_INHERIT)
300 { 329 {
diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c
index c5a2f57343..a0fd7d4608 100644
--- a/src/lib/ecore/efl_exe.c
+++ b/src/lib/ecore/efl_exe.c
@@ -357,8 +357,10 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
357 return EINA_FALSE; 357 return EINA_FALSE;
358#else 358#else
359 Eo *loop; 359 Eo *loop;
360 Efl_Task_Data *tdl, *td = efl_data_scope_get(obj, EFL_TASK_CLASS); 360 Efl_Task_Data *tdl = NULL, *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
361 Eina_Iterator *itr = NULL, *itr2 = NULL;
361 const char *cmd; 362 const char *cmd;
363 char **newenv, **env = NULL, **e;
362 int devnull; 364 int devnull;
363 int pipe_stdin[2]; 365 int pipe_stdin[2];
364 int pipe_stdout[2]; 366 int pipe_stdout[2];
@@ -428,9 +430,17 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
428 } 430 }
429 431
430 _ecore_signal_pid_lock(); 432 _ecore_signal_pid_lock();
433 // get these before the fork to avoid heap malloc deadlocks
434 loop = efl_provider_find(obj, EFL_LOOP_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);
437 if (pd->env) itr2 = efl_core_env_content_get(pd->env);
431 pd->pid = fork(); 438 pd->pid = fork();
439
432 if (pd->pid != 0) 440 if (pd->pid != 0)
433 { 441 {
442 if (itr) eina_iterator_free(itr);
443 if (itr2) eina_iterator_free(itr2);
434 // parent process is here inside this if block 444 // parent process is here inside this if block
435 if (td->flags & EFL_TASK_FLAGS_USE_STDIN) close(pipe_stdin[0]); 445 if (td->flags & EFL_TASK_FLAGS_USE_STDIN) close(pipe_stdin[0]);
436 if (td->flags & EFL_TASK_FLAGS_USE_STDOUT) close(pipe_stdout[1]); 446 if (td->flags & EFL_TASK_FLAGS_USE_STDOUT) close(pipe_stdout[1]);
@@ -513,58 +523,77 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
513 close(devnull); 523 close(devnull);
514 } 524 }
515 525
516 if (!(loop = efl_provider_find(obj, EFL_LOOP_CLASS))) exit(1); 526 if (!tdl) exit(1);
517
518 if (!(tdl = efl_data_scope_get(loop, EFL_TASK_CLASS))) exit(1);
519 527
520 // clear systemd notify socket... only relevant for systemd world, 528 // clear systemd notify socket... only relevant for systemd world,
521 // otherwise shouldn't be trouble 529 // otherwise shouldn't be trouble
522 putenv("NOTIFY_SOCKET="); 530# if defined (__FreeBSD__) || defined (__OpenBSD__)
531 _dl_environ = dlsym(NULL, "environ");
532 if (_dl_environ) env = *_dl_environ;
533# else
534 env = environ;
535# endif
536 if (env)
537 {
538 Eina_Bool shuffle = EINA_FALSE;
539
540 for (e = env; *e; e++)
541 {
542 if (!shuffle)
543 {
544 if (!strncmp(e[0], "NOTIFY_SOCKET=", 14))
545 shuffle = EINA_TRUE;
546 }
547 if (shuffle) e[0] = e[1];
548 }
549 }
523 550
524 // actually setenv the env object (clear what was there before so it is 551 // actually setenv the env object (clear what was there before so it is
525 // the only env there) 552 // the only env there)
526 if (pd->env) 553 if (pd->env)
527 { 554 {
528 Eina_Iterator *itr;
529 const char *key; 555 const char *key;
556 int count = 0, i = 0;
530 557
531# ifdef HAVE_CLEARENV 558 // use 2nd throw-away itr to count
532 clearenv(); 559 EINA_ITERATOR_FOREACH(itr2, key)
533# else 560 {
534# if defined (__FreeBSD__) || defined (__OpenBSD__) 561 count++;
535 _dl_environ = dlsym(NULL, "environ"); 562 }
536 if (_dl_environ) *_dl_environ = NULL; 563 // object which we don't free (sitting in hash table in env obj)
537 else ERR("Can't find envrion symbol"); 564 newenv = alloca(sizeof(char *) * (count + 1));
538# else 565 // use 2st iter to walk and fill new env
539 environ = NULL;
540# endif
541# endif
542 itr = efl_core_env_content_get(pd->env);
543
544 EINA_ITERATOR_FOREACH(itr, key) 566 EINA_ITERATOR_FOREACH(itr, key)
545 { 567 {
546 setenv(key, efl_core_env_get(pd->env, key) , 1); 568 newenv[i] = (char *)efl_core_env_get(pd->env, key);
569 i++;
547 } 570 }
548 efl_unref(pd->env); 571 // yes - we dont free itr or itr2 - we're going to exec below or exit
549 pd->env = NULL; 572 // also put newenv array on stack pointign to the strings in the env
573# if defined (__FreeBSD__) || defined (__OpenBSD__)
574 if (_dl_environ) *_dl_environ = newenv;
575 else ERR("Can't find envrion symbol");
576# else
577 environ = newenv;
578# endif
550 } 579 }
551 580
552 // close all fd's other than the first 3 (0, 1, 2) and exited write fd 581 // close all fd's other than the first 3 (0, 1, 2) and exited write fd
553 int except[2] = { 0, -1 }; 582 int except[2] = { 0, -1 };
554 except[0] = pd->fd.exited_write; 583 except[0] = pd->fd.exited_write;
555 eina_file_close_from(3, except); 584 eina_file_close_from(3, except);
556#ifdef HAVE_PRCTL 585# ifdef HAVE_PRCTL
557 if ((pd->flags & EFL_EXE_FLAGS_TERM_WITH_PARENT)) 586 if ((pd->flags & EFL_EXE_FLAGS_TERM_WITH_PARENT))
558 { 587 {
559 prctl(PR_SET_PDEATHSIG, SIGTERM); 588 prctl(PR_SET_PDEATHSIG, SIGTERM);
560 } 589 }
561#elif defined(HAVE_PROCCTL) 590# elif defined(HAVE_PROCCTL)
562 if ((pd->flags & EFL_EXE_FLAGS_TERM_WITH_PARENT)) 591 if ((pd->flags & EFL_EXE_FLAGS_TERM_WITH_PARENT))
563 { 592 {
564 int sig = SIGTERM; 593 int sig = SIGTERM;
565 procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sig); 594 procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sig);
566 } 595 }
567#endif 596# endif
568 // actually execute! 597 // actually execute!
569 _exec(cmd, pd->flags, td->flags); 598 _exec(cmd, pd->flags, td->flags);
570 // we couldn't exec... uh oh. HAAAAAAAALP! 599 // we couldn't exec... uh oh. HAAAAAAAALP!