From 07e851fcc8e0be7ff907ef01beb9d53c865958c0 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 7 May 2020 16:12:11 +0400 Subject: [PATCH 1/4] Fork when starting application and wait for process to complete This allows parent don't be lost when, e.g., application restarts --- AppRun.c.patch | 71 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/AppRun.c.patch b/AppRun.c.patch index d408b38..0609bf6 100644 --- a/AppRun.c.patch +++ b/AppRun.c.patch @@ -1,32 +1,81 @@ --- a/AppRun.c +++ b/AppRun.c -@@ -164,6 +164,10 @@ - char *old_env; +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #define die(...) \ + do { \ +@@ -102,6 +103,11 @@ + line[n] = '\0'; + } + ++ int pid; ++ if ((pid = fork()) == -1) { ++ int error = errno; ++ die("fork() failed: %s\n", strerror(error)); ++ } else if (pid == 0) { + // count arguments + char* arg = exe; + int argcount = 0; +@@ -165,6 +171,11 @@ size_t length; const char *format; + + checkrt(usr_in_appdir); + + if (optional_ld_preload) + putenv(optional_ld_preload); - ++ /* https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHOME */ SET_NEW_ENV(new_pythonhome, appdir_s, "PYTHONHOME=%s/usr/", appdir); -@@ -172,7 +176,7 @@ + +@@ -172,7 +183,7 @@ SET_NEW_ENV(new_path, appdir_s*5 + strlen(old_env), "PATH=%s/usr/bin/:%s/usr/sbin/:%s/usr/games/:%s/bin/:%s/sbin/:%s", appdir, appdir, appdir, appdir, appdir, old_env); old_env = getenv("LD_LIBRARY_PATH") ?: ""; - SET_NEW_ENV(new_ld_library_path, appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); + SET_NEW_ENV(new_ld_library_path, strlen(optional_ld_library_path) + appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", optional_ld_library_path, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); - + old_env = getenv("PYTHONPATH") ?: ""; SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); -@@ -201,6 +205,9 @@ - if (ret == -1) - die("Error executing '%s': %s\n", exe, strerror(error)); - +@@ -197,15 +208,12 @@ + putenv("PYTHONDONTWRITEBYTECODE=1"); + + /* Run */ +- ret = execvp(exe, outargptrs); +- +- int error = errno; ++ execvp(exe, outargptrs); + +- if (ret == -1) +- die("Error executing '%s': %s\n", exe, strerror(error)); + free(optional_ld_library_path); + if (optional_ld_preload) + free(optional_ld_preload); - free(line); - free(desktop_file); + +- free(line); +- free(desktop_file); free(usr_in_appdir); + free(new_pythonhome); + free(new_path); +@@ -215,5 +223,16 @@ + free(new_perllib); + free(new_gsettings_schema_dir); + free(new_qt_plugin_path); +- return 0; ++ ++ int error = errno; ++ die("Error executing '%s': %s\n", exe, strerror(error)); ++ } ++ ++ int status = 0; ++ int rv = waitpid(pid, &status, 0); ++ status = rv > 0 && WIFEXITED (status) ? WEXITSTATUS (status) : 1; ++ ++ free(line); ++ free(desktop_file); ++ return status; + } From b2ac83a76e5e032fde2a376f587dd8cd66526508 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 7 May 2020 16:17:06 +0400 Subject: [PATCH 2/4] I don't know why, but getppid() returns wrong result for me when application is started --- AppRun.c.patch | 27 ++++++++++++++++++++++----- env.c | 17 ++++++++++++++++- env.h | 1 + exec.c | 2 +- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/AppRun.c.patch b/AppRun.c.patch index 0609bf6..edef26f 100644 --- a/AppRun.c.patch +++ b/AppRun.c.patch @@ -41,17 +41,34 @@ old_env = getenv("PYTHONPATH") ?: ""; SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); -@@ -197,15 +208,12 @@ +@@ -196,16 +207,29 @@ + /* Otherwise may get errors because Python cannot write __pycache__ bytecode cache */ putenv("PYTHONDONTWRITEBYTECODE=1"); - /* Run */ +- /* Run */ - ret = execvp(exe, outargptrs); -- ++ /* Set pid & ppid */ ++ pid_t pid = getpid(); ++ pid_t ppid = getppid(); + - int error = errno; -+ execvp(exe, outargptrs); ++ int pid_len = snprintf(NULL, 0, "%d", pid); ++ int ppid_len = snprintf(NULL, 0, "%d", ppid); - if (ret == -1) - die("Error executing '%s': %s\n", exe, strerror(error)); ++ char *s_pid = malloc(pid_len + 1); ++ snprintf(s_pid, pid_len + 1, "%d", pid); ++ ++ char *s_ppid = malloc(ppid_len + 1); ++ snprintf(s_ppid, ppid_len + 1, "%d", ppid); ++ ++ setenv("PID", s_pid, 1); ++ setenv("PPID", s_ppid, 1); ++ ++ /* Run */ ++ execvp(exe, outargptrs); ++ + free(optional_ld_library_path); + if (optional_ld_preload) + free(optional_ld_preload); @@ -61,7 +78,7 @@ free(usr_in_appdir); free(new_pythonhome); free(new_path); -@@ -215,5 +223,16 @@ +@@ -215,5 +239,16 @@ free(new_perllib); free(new_gsettings_schema_dir); free(new_qt_plugin_path); diff --git a/env.c b/env.c index 6776bff..9c1d476 100755 --- a/env.c +++ b/env.c @@ -43,6 +43,21 @@ void env_free(char* const *env) { free((char**)env); } +pid_t get_parent_pid() { + pid_t ppid = 0; + char *s_ppid = getenv("PPID"); + + if(s_ppid) { + ppid = atoi(s_ppid); + } + + if (!ppid) { + ppid = getppid(); + } + + return ppid; +} + static size_t get_number_of_variables(FILE *file, char **buffer, size_t *len) { size_t number = 0; @@ -103,7 +118,7 @@ static char* const* read_env_from_process(pid_t pid) { } char* const* read_parent_env() { - pid_t ppid = getppid(); + pid_t ppid = get_parent_pid(); return read_env_from_process(ppid); } diff --git a/env.h b/env.h index affc2d4..36f491c 100755 --- a/env.h +++ b/env.h @@ -3,6 +3,7 @@ #include +pid_t get_parent_pid(); char* const* read_parent_env(); void env_free(char* const *env); diff --git a/exec.c b/exec.c index ad0f489..8d54b02 100644 --- a/exec.c +++ b/exec.c @@ -79,7 +79,7 @@ static int exec_common(execve_func_t function, const char *filename, char* const DEBUG("filename %s, fullpath %s\n", filename, fullpath); char* const *env = envp; if (is_external_process(fullpath)) { - DEBUG("External process detected. Restoring env vars from parent %d\n", getppid()); + DEBUG("External process detected. Restoring env vars from parent %d\n", get_parent_pid()); env = read_parent_env(); if (!env) env = envp; From 3c8564782664b59e005ce908373ad89d4ed6ec53 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 7 May 2020 16:18:40 +0400 Subject: [PATCH 3/4] Fix displaying error message when parent enviornment can'be restored --- exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index 8d54b02..29d04ec 100644 --- a/exec.c +++ b/exec.c @@ -81,10 +81,10 @@ static int exec_common(execve_func_t function, const char *filename, char* const if (is_external_process(fullpath)) { DEBUG("External process detected. Restoring env vars from parent %d\n", get_parent_pid()); env = read_parent_env(); - if (!env) + if (!env) { env = envp; - else DEBUG("Error restoring env vars from parent\n"); + } } int ret = function(filename, argv, env); From ac29d2960d91ecf628e97895cd2890efb564958c Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 7 May 2020 16:19:16 +0400 Subject: [PATCH 4/4] Fix path to AppRun.c in Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cd8fe34..dab0cff 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,6 @@ AppRun_patched.c: AppRun.c patch -p1 --output $@ < AppRun.c.patch AppRun.c: - wget -c "https://raw.githubusercontent.com/AppImage/AppImageKit/appimagetool/master/src/AppRun.c" + wget -c "https://raw.githubusercontent.com/AppImage/AppImageKit/master/src/AppRun.c" .PHONY: checkrt test run_tests all clean