mirror of
https://github.com/moparisthebest/pacman
synced 2025-01-09 04:57:59 -05:00
redirect scriptlet stderr synchronously through alpm
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@skurvy.no-ip.org> Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
parent
d14a98db25
commit
0223a028e0
@ -456,6 +456,7 @@ int _alpm_run_chroot(const char *root, const char *cmd)
|
|||||||
{
|
{
|
||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int pipefd[2];
|
||||||
int restore_cwd = 0;
|
int restore_cwd = 0;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
@ -479,6 +480,12 @@ int _alpm_run_chroot(const char *root, const char *cmd)
|
|||||||
/* Flush open fds before fork() to avoid cloning buffers */
|
/* Flush open fds before fork() to avoid cloning buffers */
|
||||||
fflush(NULL);
|
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 */
|
/* fork- parent and child each have seperate code blocks below */
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid == -1) {
|
if(pid == -1) {
|
||||||
@ -488,26 +495,38 @@ int _alpm_run_chroot(const char *root, const char *cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(pid == 0) {
|
if(pid == 0) {
|
||||||
FILE *pipe;
|
|
||||||
/* this code runs for the child only (the actual chroot/exec) */
|
/* 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);
|
||||||
|
while(dup2(pipefd[1], 1) == -1 && errno == EINTR);
|
||||||
|
while(dup2(pipefd[1], 2) == -1 && errno == EINTR);
|
||||||
|
close(pipefd[0]);
|
||||||
|
close(pipefd[1]);
|
||||||
|
|
||||||
|
/* use fprintf instead of _alpm_log to send output through the parent */
|
||||||
if(chroot(root) != 0) {
|
if(chroot(root) != 0) {
|
||||||
_alpm_log(PM_LOG_ERROR, _("could not change the root directory (%s)\n"),
|
fprintf(stderr, _("could not change the root directory (%s)\n"), strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(chdir("/") != 0) {
|
if(chdir("/") != 0) {
|
||||||
_alpm_log(PM_LOG_ERROR, _("could not change directory to / (%s)\n"),
|
fprintf(stderr, _("could not change directory to / (%s)\n"), strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
umask(0022);
|
umask(0022);
|
||||||
pipe = popen(cmd, "r");
|
execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
|
||||||
if(!pipe) {
|
fprintf(stderr, _("call to execl failed (%s)\n"), strerror(errno));
|
||||||
_alpm_log(PM_LOG_ERROR, _("call to popen failed (%s)\n"),
|
|
||||||
strerror(errno));
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
} else {
|
||||||
|
/* this code runs for the parent only (wait on the child) */
|
||||||
|
int status;
|
||||||
|
FILE *pipe;
|
||||||
|
|
||||||
|
close(pipefd[1]);
|
||||||
|
pipe = fdopen(pipefd[0], "r");
|
||||||
|
if(pipe == NULL) {
|
||||||
|
close(pipefd[0]);
|
||||||
|
retval = 1;
|
||||||
|
} else {
|
||||||
while(!feof(pipe)) {
|
while(!feof(pipe)) {
|
||||||
char line[PATH_MAX];
|
char line[PATH_MAX];
|
||||||
if(fgets(line, PATH_MAX, pipe) == NULL)
|
if(fgets(line, PATH_MAX, pipe) == NULL)
|
||||||
@ -515,21 +534,22 @@ int _alpm_run_chroot(const char *root, const char *cmd)
|
|||||||
alpm_logaction("%s", line);
|
alpm_logaction("%s", line);
|
||||||
EVENT(handle->trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL);
|
EVENT(handle->trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL);
|
||||||
}
|
}
|
||||||
retval = pclose(pipe);
|
fclose(pipe);
|
||||||
exit(WEXITSTATUS(retval));
|
}
|
||||||
} else {
|
|
||||||
/* this code runs for the parent only (wait on the child) */
|
while(waitpid(pid, &status, 0) == -1) {
|
||||||
pid_t retpid;
|
if(errno != EINTR) {
|
||||||
int status;
|
_alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno));
|
||||||
do {
|
|
||||||
retpid = waitpid(pid, &status, 0);
|
|
||||||
} while(retpid == -1 && errno == EINTR);
|
|
||||||
if(retpid == -1) {
|
|
||||||
_alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"),
|
|
||||||
strerror(errno));
|
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* report error from above after the child has exited */
|
||||||
|
if(retval != 0) {
|
||||||
|
_alpm_log(PM_LOG_ERROR, _("could not open pipe (%s)\n"), strerror(errno));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
/* check the return status, make sure it is 0 (success) */
|
/* check the return status, make sure it is 0 (success) */
|
||||||
if(WIFEXITED(status)) {
|
if(WIFEXITED(status)) {
|
||||||
_alpm_log(PM_LOG_DEBUG, "call to waitpid succeeded\n");
|
_alpm_log(PM_LOG_DEBUG, "call to waitpid succeeded\n");
|
||||||
@ -539,7 +559,6 @@ int _alpm_run_chroot(const char *root, const char *cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if(restore_cwd && chdir(cwd) != 0) {
|
if(restore_cwd && chdir(cwd) != 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user