blob: 0ff847365921a508ac36dca99422d33ce6b9ce18 [file] [log] [blame]
foomatic-rip failure status fix
Changes execution of renderer thread in the foomatic-rip package to fail
whenever any of its individual sub-comands fails.
Parent process now ignores SIGPIPE calls from upstream/downstream CUPS filters,
per https://www.cups.org/doc/api-filter.html, while correctly noting child
process failures and exiting accordingly.
NOTE: Child processes still abort on SIGPIPE. It is now the responsibility
of the parent to note this crash and exit gracefully.
Reported here:
https://bugs.linuxfoundation.org/show_bug.cgi?id=1412
diff -u filter/foomatic-rip/foomaticrip.c filter-new/foomatic-rip/foomaticrip.c
--- filter/foomatic-rip/foomaticrip.c 2015-10-20 07:59:20.000000000 -0700
+++ filter-new/foomatic-rip/foomaticrip.c 2017-09-26 10:37:23.747220621 -0700
@@ -517,7 +517,7 @@
while (isspace(*p++) && left-- > 0)
;
- fwrite((void *)p, left, 1, postpipe);
+ fwrite_or_die((void *)p, left, 1, postpipe);
fflush(postpipe);
}
@@ -572,7 +572,7 @@
}
}
- n = fread(buf, 1, sizeof(buf) - 1, file);
+ n = fread_or_die(buf, 1, sizeof(buf) - 1, file);
buf[n] = '\0';
type = guess_file_type(buf, n, &startpos);
/* We do not use any JCL preceeded to the inputr data, as it is simply
@@ -745,6 +745,7 @@
signal(SIGTERM, signal_terminate);
signal(SIGINT, signal_terminate);
+ signal(SIGPIPE, SIG_IGN);
config_from_file(CONFIG_PATH "/filter.conf");
diff -u filter/foomatic-rip/pdf.c filter-new/foomatic-rip/pdf.c
--- filter/foomatic-rip/pdf.c 2015-10-09 18:32:52.000000000 -0700
+++ filter-new/foomatic-rip/pdf.c 2017-09-26 10:37:23.751220608 -0700
@@ -56,7 +56,7 @@
if (!pd)
rip_die(EXIT_STARVED, "Failed to execute ghostscript to determine number of input pages!\n");
- bytes = fread(output, 1, 31, pd);
+ bytes = fread_or_die(output, 1, 31, pd);
pclose(pd);
if (bytes <= 0 || sscanf(output, "PageCount: %d", &pagecount) < 1)
diff -u filter/foomatic-rip/postscript.c filter-new/foomatic-rip/postscript.c
--- filter/foomatic-rip/postscript.c 2015-07-04 04:21:47.000000000 -0700
+++ filter-new/foomatic-rip/postscript.c 2017-09-26 10:36:29.279398863 -0700
@@ -1032,14 +1032,14 @@
if (!isempty(psfifo->data)) {
/* Send psfifo to renderer */
- fwrite(psfifo->data, psfifo->len, 1, rendererhandle);
+ fwrite_or_die(psfifo->data, psfifo->len, 1, rendererhandle);
/* flush psfifo */
dstrclear(psfifo);
}
/* Send line to renderer */
if (!printprevpage) {
- fwrite(line->data, line->len, 1, rendererhandle);
+ fwrite_or_die(line->data, line->len, 1, rendererhandle);
while (stream_next_line(line, stream) > 0) {
if (startswith(line->data, "%%")) {
@@ -1049,7 +1049,7 @@
break;
}
else {
- fwrite(line->data, line->len, 1, rendererhandle);
+ fwrite_or_die(line->data, line->len, 1, rendererhandle);
linect++;
}
}
@@ -1141,14 +1141,14 @@
if (psfifo->len) {
/* Send psfifo to the renderer */
- fwrite(psfifo->data, psfifo->len, 1, rendererhandle);
+ fwrite_or_die(psfifo->data, psfifo->len, 1, rendererhandle);
dstrclear(psfifo);
}
/* Print the rest of the input data */
if (more_stuff) {
while (stream_next_line(tmp, stream))
- fwrite(tmp->data, tmp->len, 1, rendererhandle);
+ fwrite_or_die(tmp->data, tmp->len, 1, rendererhandle);
}
}
@@ -1197,7 +1197,7 @@
/* Feed the PostScript header and the FIFO contents */
if (prepend)
- fwrite(prepend->data, prepend->len, 1, kid3in);
+ fwrite_or_die(prepend->data, prepend->len, 1, kid3in);
/* We are the parent, return glob to the file handle */
*fd = kid3in;
diff -u filter/foomatic-rip/process.c filter-new/foomatic-rip/process.c
--- filter/foomatic-rip/process.c 2015-07-04 04:21:47.000000000 -0700
+++ filter-new/foomatic-rip/process.c 2017-09-25 12:54:46.279584580 -0700
@@ -125,6 +125,10 @@
}
if (pid == 0) { /* Child */
+
+ // Reset sigpipe behavior to default for all children
+ signal(SIGPIPE, SIG_DFL);
+
if (pipe_in) {
close(pfdin[1]);
in = fdopen(pfdin[0], "r");
@@ -179,7 +183,7 @@
if (out && dup2(fileno(out), fileno(stdout)) < 0)
rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "%s: Could not dup stdout\n", (const char *)cmd);
- execl(get_modern_shell(), get_modern_shell(), "-c", (const char *)cmd, (char *)NULL);
+ execl(get_modern_shell(), get_modern_shell(), "-e", "-c", (const char *)cmd, (char *)NULL);
_log("Error: Executing \"%s -c %s\" failed (%s).\n", get_modern_shell(), (const char *)cmd, strerror(errno));
return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
diff -u filter/foomatic-rip/renderer.c filter-new/foomatic-rip/renderer.c
--- filter/foomatic-rip/renderer.c 2015-07-04 04:21:47.000000000 -0700
+++ filter-new/foomatic-rip/renderer.c 2017-09-26 10:37:23.751220608 -0700
@@ -52,7 +52,7 @@
return 0;
}
- bytes = fread(output, 1, 10, pd);
+ bytes = fread_or_die(output, 1, 10, pd);
pclose(pd);
if (bytes > 0 && startswith(output, "hello"))
@@ -288,7 +288,7 @@
* also contains the "<esc>%-12345X" which has to be in the beginning
* of the job */
if (p)
- fwrite(original_opts[0], 1, p - original_opts[0], stream);
+ fwrite_or_die(original_opts[0], 1, p - original_opts[0], stream);
else
fprintf(stream, "%s\n", original_opts[0]);
@@ -392,7 +392,7 @@
/* A JCL trailer */
if (argv_count(jclprepend) > 0 && !driverjcl)
- fwrite(jclappend->data, jclappend->len, 1, fileh);
+ fwrite_or_die(jclappend->data, jclappend->len, 1, fileh);
fclose(in);
if (fclose(fileh) != 0)
diff -u filter/foomatic-rip/util.c filter-new/foomatic-rip/util.c
--- filter/foomatic-rip/util.c 2015-12-12 15:21:05.000000000 -0800
+++ filter-new/foomatic-rip/util.c 2017-09-26 10:37:23.759220582 -0700
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <stdarg.h>
#include <assert.h>
+#include <errno.h>
const char* shellescapes = "|;<>&!$\'\"`#*?()[]{}";
@@ -291,6 +292,22 @@
return psrc +1;
}
+size_t fwrite_or_die(const void* ptr, size_t size, size_t count, FILE* stream) {
+ size_t res = fwrite(ptr, size, count, stream);
+ if (ferror(stream))
+ rip_die(EXIT_PRNERR, "Encountered error %s during fwrite", strerror(errno));
+
+ return res;
+}
+
+size_t fread_or_die(void* ptr, size_t size, size_t count, FILE* stream) {
+ size_t res = fread(ptr, size, count, stream);
+ if (ferror(stream))
+ rip_die(EXIT_PRNERR, "Encountered error %s during fread", strerror(errno));
+
+ return res;
+}
+
int find_in_path(const char *progname, const char *paths, char *found_in)
{
char *pathscopy;
@@ -1111,15 +1128,15 @@
if (alreadyread && alreadyread_len)
{
- if (fwrite(alreadyread, 1, alreadyread_len, dest) < alreadyread_len)
+ if (fwrite_or_die(alreadyread, 1, alreadyread_len, dest) < alreadyread_len)
{
_log("Could not write to temp file\n");
return 0;
}
}
- while ((bytes = fread(buf, 1, 8192, src)))
- fwrite(buf, 1, bytes, dest);
+ while ((bytes = fread_or_die(buf, 1, 8192, src)))
+ fwrite_or_die(buf, 1, bytes, dest);
return !ferror(src) && !ferror(dest);
}
diff -u filter/foomatic-rip/util.h filter-new/foomatic-rip/util.h
--- filter/foomatic-rip/util.h 2015-06-26 08:45:26.000000000 -0700
+++ filter-new/foomatic-rip/util.h 2017-09-26 10:38:16.443048131 -0700
@@ -98,6 +98,11 @@
*/
const char * strncpy_tochar(char *dest, const char *src, size_t max, const char *stopchars);
+/* "safe" versions of standard <cstdio> fwrite and fread that will cause the
+ * program to exit gracefully when a write/read fails */
+size_t fwrite_or_die(const void* ptr, size_t size, size_t count, FILE* stream);
+size_t fread_or_die(void* ptr, size_t size, size_t count, FILE* stream);
+
/* 'paths' is a colon seperated list of paths (like $PATH)
* 'found_in' may be NULL if it is not needed */
int find_in_path(const char *progname, const char *paths, char *found_in);