From 3cb98280b88f1e04d17284da70ffe581d77739a1 Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Sat, 15 Sep 2012 16:32:37 +0200 Subject: [PATCH] Fix hang in gstoraster if gs fails (bug #693336) Set up a child reaper to properly kill the gs process when it fails, and avoid it being a zombie. Otherwise, if gs fails and the input file is bigger than the pipe capacity (65536 bytes on Linux), gstoraster will hang in write() because the pipe is full and the reader is not gone but is still a zombie. --- cups/gstoraster.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/cups/gstoraster.c b/cups/gstoraster.c index 1250be5..bd64030 100644 --- a/cups/gstoraster.c +++ b/cups/gstoraster.c @@ -38,6 +38,8 @@ MIT Open Source License - http://www.opensource.org/ #include #include #include +#include +#include #include "colord.h" @@ -423,7 +425,10 @@ gs_spawn (const char *filename, /* Feed job data into Ghostscript */ while ((n = fread(buf, 1, BUFSIZ, fp)) > 0) { - if (write(fds[1], buf, n) != n) { + int count = write(fds[1], buf, n); + if (count != n) { + if (count == -1) + fprintf(stderr, "ERROR: write failed: %s\n", strerror(errno)); fprintf(stderr, "ERROR: Can't feed job data into Ghostscript\n"); goto out; } @@ -510,6 +515,12 @@ out: return icc_profile; } +static void +child_reaper (int signum) +{ + wait(NULL); +} + int main (int argc, char **argv, char *envp[]) { @@ -530,6 +541,7 @@ main (int argc, char **argv, char *envp[]) int num_options; int status = 1; ppd_file_t *ppd = NULL; + struct sigaction sa; if (argc < 6 || argc > 7) { fprintf(stderr, "ERROR: %s job-id user title copies options [file]\n", @@ -537,6 +549,14 @@ main (int argc, char **argv, char *envp[]) goto out; } + memset(&sa, 0, sizeof(sa)); + /* Ignore SIGPIPE and have write return an error instead */ + sa.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &sa, NULL); + + sa.sa_handler = child_reaper; + sigaction(SIGCHLD, &sa, NULL); + num_options = cupsParseOptions(argv[5], 0, &options); t = getenv("PPD"); -- 1.7.12