aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libsbutil/sb_efuncs.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/libsbutil/sb_efuncs.c b/libsbutil/sb_efuncs.c
index 6a7a09b..64ac82f 100644
--- a/libsbutil/sb_efuncs.c
+++ b/libsbutil/sb_efuncs.c
@@ -26,7 +26,7 @@ static void sbio_init(void)
}
}
-static bool try_portage_helpers = false;
+static bool try_portage_helpers = true;
/*
* First try to use the helper programs from portage so that it can sanely
@@ -39,17 +39,20 @@ static void sb_vefunc(const char *prog, const char *color, const char *format, v
{
char shellcode[128];
FILE *fp;
- sighandler_t oldsig;
+ struct sigaction sa, old_sa;
bool is_pipe = false;
+ va_list retry_args;
if (try_portage_helpers) {
/* If popen() fails, then writes to it will trigger SIGPIPE */
- /* XXX: convert this to sigaction */
- oldsig = signal(SIGPIPE, SIG_IGN);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, &old_sa);
sprintf(shellcode, "xargs %s 2>/dev/null", prog);
fp = sbio_popen(shellcode, "we");
is_pipe = true;
+ va_copy(retry_args, args);
} else
fp = NULL;
@@ -68,13 +71,20 @@ static void sb_vefunc(const char *prog, const char *color, const char *format, v
if (is_pipe) {
int status = pclose(fp);
- if (WEXITSTATUS(status))
+ if (WEXITSTATUS(status)) {
+ args = retry_args;
goto do_tty;
+ }
} else if (fp != stderr)
fclose(fp);
- if (try_portage_helpers)
- signal(SIGPIPE, oldsig);
+ if (try_portage_helpers) {
+ sigaction(SIGCHLD, &old_sa, NULL);
+ va_end(retry_args);
+ if (!is_pipe)
+ /* If we failed once, we'll fail again */
+ try_portage_helpers = false;
+ }
}
void sb_einfo(const char *format, ...)