Commit 1fc7241e authored by Mark Adler's avatar Mark Adler

Do not abort on inflate data error -- continue to process files.

This introduces try/catch/throw for error handling throughout pigz.
Each thread has its own try stack for error handling.  If a throw
makes it to the top try in a thread, then the entire program is
aborted.  Data errors caught during decoding and decompression
permit the process to continue with subsequent files.
parent 7ff80327
......@@ -4,14 +4,16 @@ LDFLAGS=-lz
ZOPFLI=zopfli/src/zopfli/
# use gcc and gmake on Solaris
pigz: pigz.o yarn.o ${ZOPFLI}deflate.o ${ZOPFLI}blocksplitter.o ${ZOPFLI}tree.o ${ZOPFLI}lz77.o ${ZOPFLI}cache.o ${ZOPFLI}hash.o ${ZOPFLI}util.o ${ZOPFLI}squeeze.o ${ZOPFLI}katajainen.o
pigz: pigz.o yarn.o try.o ${ZOPFLI}deflate.o ${ZOPFLI}blocksplitter.o ${ZOPFLI}tree.o ${ZOPFLI}lz77.o ${ZOPFLI}cache.o ${ZOPFLI}hash.o ${ZOPFLI}util.o ${ZOPFLI}squeeze.o ${ZOPFLI}katajainen.o
$(CC) $(LDFLAGS) -o pigz $^ -lpthread -lm
ln -f pigz unpigz
pigz.o: pigz.c yarn.h ${ZOPFLI}deflate.h ${ZOPFLI}util.h
pigz.o: pigz.c yarn.h try.h ${ZOPFLI}deflate.h ${ZOPFLI}util.h
yarn.o: yarn.c yarn.h
try.o: try.c try.h
${ZOPFLI}deflate.o: ${ZOPFLI}deflate.c ${ZOPFLI}deflate.h ${ZOPFLI}blocksplitter.h ${ZOPFLI}lz77.h ${ZOPFLI}squeeze.h ${ZOPFLI}tree.h ${ZOPFLI}zopfli.h ${ZOPFLI}cache.h ${ZOPFLI}hash.h ${ZOPFLI}util.h
${ZOPFLI}blocksplitter.o: ${ZOPFLI}blocksplitter.c ${ZOPFLI}blocksplitter.h ${ZOPFLI}deflate.h ${ZOPFLI}lz77.h ${ZOPFLI}squeeze.h ${ZOPFLI}tree.h ${ZOPFLI}util.h ${ZOPFLI}zopfli.h ${ZOPFLI}cache.h ${ZOPFLI}hash.h
......@@ -32,21 +34,24 @@ ${ZOPFLI}katajainen.o: ${ZOPFLI}katajainen.c ${ZOPFLI}katajainen.h
dev: pigz pigzt pigzn
pigzt: pigzt.o yarnt.o ${ZOPFLI}deflate.o ${ZOPFLI}blocksplitter.o ${ZOPFLI}tree.o ${ZOPFLI}lz77.o ${ZOPFLI}cache.o ${ZOPFLI}hash.o ${ZOPFLI}util.o ${ZOPFLI}squeeze.o ${ZOPFLI}katajainen.o
pigzt: pigzt.o yarnt.o try.o ${ZOPFLI}deflate.o ${ZOPFLI}blocksplitter.o ${ZOPFLI}tree.o ${ZOPFLI}lz77.o ${ZOPFLI}cache.o ${ZOPFLI}hash.o ${ZOPFLI}util.o ${ZOPFLI}squeeze.o ${ZOPFLI}katajainen.o
$(CC) $(LDFLAGS) -o pigzt $^ -lpthread -lm
pigzt.o: pigz.c yarn.h
pigzt.o: pigz.c yarn.h try.h
$(CC) $(CFLAGS) -DDEBUG -g -c -o pigzt.o pigz.c
yarnt.o: yarn.c yarn.h
$(CC) $(CFLAGS) -DDEBUG -g -c -o yarnt.o yarn.c
pigzn: pigzn.o ${ZOPFLI}deflate.o ${ZOPFLI}blocksplitter.o ${ZOPFLI}tree.o ${ZOPFLI}lz77.o ${ZOPFLI}cache.o ${ZOPFLI}hash.o ${ZOPFLI}util.o ${ZOPFLI}squeeze.o ${ZOPFLI}katajainen.o
pigzn: pigzn.o tryn.o ${ZOPFLI}deflate.o ${ZOPFLI}blocksplitter.o ${ZOPFLI}tree.o ${ZOPFLI}lz77.o ${ZOPFLI}cache.o ${ZOPFLI}hash.o ${ZOPFLI}util.o ${ZOPFLI}squeeze.o ${ZOPFLI}katajainen.o
$(CC) $(LDFLAGS) -o pigzn $^ -lm
pigzn.o: pigz.c
pigzn.o: pigz.c try.h
$(CC) $(CFLAGS) -DDEBUG -DNOTHREAD -g -c -o pigzn.o pigz.c
tryn.o: try.c try.h
$(CC) $(CFLAGS) -DDEBUG -DNOTHREAD -g -c -o tryn.o try.c
test: pigz
./pigz -kf pigz.c ; ./pigz -t pigz.c.gz
./pigz -kfb 32 pigz.c ; ./pigz -t pigz.c.gz
......
This diff is collapsed.
/* try.c -- try / catch / throw exception handling for C99
* Copyright (C) 2013, 2015 Mark Adler
* Version 1.2 19 January 2015
* For conditions of distribution and use, see copyright notice in try.h
*/
/* See try.h for documentation. This source file provides the global pointer
and the functions needed by throw(). The pointer is thread-unique if
pthread.h is included in try.h. */
#include "try.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
/* Set up the try stack with a global pointer to the next try block. The
global is thread-unique if pthread.h is included in try.h. */
#ifdef PTHREAD_ONCE_INIT
pthread_key_t try_key_;
static pthread_once_t try_once_ = PTHREAD_ONCE_INIT;
static void try_create_(void)
{
int ret = pthread_key_create(&try_key_, NULL);
assert(ret == 0 && "try: pthread_key_create() failed");
}
void try_setup_(void)
{
int ret = pthread_once(&try_once_, try_create_);
assert(ret == 0 && "try: pthread_once() failed");
}
#else /* !PTHREAD_ONCE_INIT */
try_t_ *try_stack_ = NULL;
#endif /* PTHREAD_ONCE_INIT */
/* Throw an exception. This must always have at least two arguments, where the
second argument can be a NULL. The throw() macro is permitted to have one
argument, since it appends a NULL argument in the call to this function. */
void try_throw_(int code, char *fmt, ...)
{
/* save the thrown information in the try stack before jumping */
try_setup_();
assert(try_stack_ != NULL && "try: naked throw");
try_stack_->ball.code = code;
try_stack_->ball.free = 0;
try_stack_->ball.why = fmt;
/* consider the second argument to be a string, and if it has formatting
commands, process them with the subsequent arguments of throw, saving
the result in allocated memory -- this if statement and clause must be
updated for a different interpretation of the throw() arguments and
different contents of the ball_t structure */
if (fmt != NULL && strchr(fmt, '%') != NULL) {
char *why, nul[1];
size_t len;
va_list ap1, ap2;
va_start(ap1, fmt);
va_copy(ap2, ap1);
len = vsnprintf(nul, 1, fmt, ap1);
va_end(ap1);
why = malloc(len + 1);
if (why == NULL)
try_stack_->ball.why = "try: out of memory";
else {
vsnprintf(why, len + 1, fmt, ap2);
va_end(ap2);
try_stack_->ball.free = 1;
try_stack_->ball.why = why;
}
}
/* jump to the end of the nearest enclosing try block */
longjmp(try_stack_->env, 2);
}
This diff is collapsed.
/* yarn.c -- generic thread operations implemented using pthread functions
* Copyright (C) 2008, 2012 Mark Adler
* Version 1.3 13 Jan 2012 Mark Adler
* Copyright (C) 2008, 2011, 2012, 2015 Mark Adler
* Version 1.4 19 Jan 2015 Mark Adler
* For conditions of distribution and use, see copyright notice in yarn.h
*/
......@@ -17,6 +17,8 @@
1.3 13 Jan 2012 Add large file #define for consistency with pigz.c
Update thread portability #defines per IEEE 1003.1-2008
Fix documentation in yarn.h for yarn_prefix
1.4 19 Jan 2015 Allow yarn_abort() to avoid error message to stderr
Accept and do nothing for NULL argument to free_lock()
*/
/* for thread portability */
......@@ -54,10 +56,10 @@ void (*yarn_abort)(int) = NULL;
/* immediately exit -- use for errors that shouldn't ever happen */
local void fail(int err)
{
fprintf(stderr, "%s: %s (%d) -- aborting\n", yarn_prefix,
err == ENOMEM ? "out of memory" : "internal pthread error", err);
if (yarn_abort != NULL)
yarn_abort(err);
fprintf(stderr, "%s: %s (%d) -- aborting\n", yarn_prefix,
err == ENOMEM ? "out of memory" : "internal pthread error", err);
exit(err == ENOMEM || err == EAGAIN ? err : EINVAL);
}
......@@ -172,6 +174,9 @@ long peek_lock(lock *bolt)
void free_lock(lock *bolt)
{
int ret;
if (bolt == NULL)
return;
if ((ret = pthread_cond_destroy(&(bolt->cond))) ||
(ret = pthread_mutex_destroy(&(bolt->mutex))))
fail(ret);
......
/* yarn.h -- generic interface for thread operations
* Copyright (C) 2008, 2011 Mark Adler
* Version 1.3 13 Jan 2012 Mark Adler
* Copyright (C) 2008, 2011, 2012, 2015 Mark Adler
* Version 1.4 19 Jan 2015 Mark Adler
*/
/*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment