[pacman-dev] [PATCH] redirect scriptlet stderr through alpm
Jonathan Conder
j at skurvy.no-ip.org
Thu May 20 23:13:39 EDT 2010
Fixes FS#18770, and hopefully an occasional deadlock in my frontend as well.
For simplicity it redirects all scriptlet output through SCRIPTLET_INFO, and
all callbacks in the child process have been replaced for thread-safety.
Signed-off-by: Jonathan Conder <j at skurvy.no-ip.org>
---
lib/libalpm/util.c | 84 ++++++++++++++++++++++++++++++---------------------
1 files changed, 49 insertions(+), 35 deletions(-)
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 2b006e2..c88be2d 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -462,6 +462,7 @@ int _alpm_run_chroot(const char *root, const char *cmd)
{
char cwd[PATH_MAX];
pid_t pid;
+ int pipefd[2];
int restore_cwd = 0;
int retval = 0;
@@ -485,6 +486,12 @@ int _alpm_run_chroot(const char *root, const char *cmd)
/* Flush open fds before fork() to avoid cloning buffers */
fflush(NULL);
+ if(pipe(pipefd) == -1) {
+ _alpm_log(PM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno));
+ retval = 1;
+ goto cleanup;
+ }
+
/* fork- parent and child each have seperate code blocks below */
pid = fork();
if(pid == -1) {
@@ -494,53 +501,60 @@ int _alpm_run_chroot(const char *root, const char *cmd)
}
if(pid == 0) {
- FILE *pipe;
/* this code runs for the child only (the actual chroot/exec) */
- _alpm_log(PM_LOG_DEBUG, "chrooting in %s\n", root);
+ close(1);
+ close(2);
+ close(pipefd[0]);
+ while(dup2(pipefd[1], 1) == -1 && errno == EINTR);
+ while(dup2(pipefd[1], 2) == -1 && errno == EINTR);
+ close(pipefd[1]);
+
if(chroot(root) != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change the root directory (%s)\n"),
- strerror(errno));
+ printf(_("could not change the root directory (%s)\n"), strerror(errno));
exit(1);
}
if(chdir("/") != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change directory to / (%s)\n"),
- strerror(errno));
+ printf(_("could not change directory to / (%s)\n"), strerror(errno));
exit(1);
}
umask(0022);
- pipe = popen(cmd, "r");
- if(!pipe) {
- _alpm_log(PM_LOG_ERROR, _("call to popen failed (%s)\n"),
- strerror(errno));
- exit(1);
- }
- while(!feof(pipe)) {
- char line[PATH_MAX];
- if(fgets(line, PATH_MAX, pipe) == NULL)
- break;
- alpm_logaction("%s", line);
- EVENT(handle->trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL);
- }
- retval = pclose(pipe);
- exit(WEXITSTATUS(retval));
+ execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
+ printf(_("call to execl failed (%s)\n"), strerror(errno));
+ exit(1);
} else {
/* this code runs for the parent only (wait on the child) */
- pid_t retpid;
int status;
- while((retpid = waitpid(pid, &status, 0)) == -1 && errno == EINTR);
- if(retpid == -1) {
- _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"),
- strerror(errno));
- retval = 1;
- goto cleanup;
+ FILE *pipe;
+
+ close(pipefd[1]);
+ pipe = fdopen(pipefd[0], "r");
+ if(pipe == NULL) {
+ close(pipefd[0]);
} else {
- /* check the return status, make sure it is 0 (success) */
- if(WIFEXITED(status)) {
- _alpm_log(PM_LOG_DEBUG, "call to waitpid succeeded\n");
- if(WEXITSTATUS(status) != 0) {
- _alpm_log(PM_LOG_ERROR, _("command failed to execute correctly\n"));
- retval = 1;
- }
+ while(!feof(pipe)) {
+ char line[PATH_MAX];
+ if(fgets(line, PATH_MAX, pipe) == NULL)
+ break;
+ alpm_logaction("%s", line);
+ EVENT(handle->trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL);
+ }
+ fclose(pipe);
+ }
+
+ while(waitpid(pid, &status, 0) == -1) {
+ if(errno != EINTR) {
+ _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno));
+ retval = 1;
+ goto cleanup;
+ }
+ }
+
+ /* check the return status, make sure it is 0 (success) */
+ if(WIFEXITED(status)) {
+ _alpm_log(PM_LOG_DEBUG, "call to waitpid succeeded\n");
+ if(WEXITSTATUS(status) != 0) {
+ _alpm_log(PM_LOG_ERROR, _("command failed to execute correctly\n"));
+ retval = 1;
}
}
}
--
1.7.1
More information about the pacman-dev
mailing list