diff options
author | Luca Barbato <lu_zero@gentoo.org> | 2013-07-07 01:52:51 +0200 |
---|---|---|
committer | Luca Barbato <lu_zero@gentoo.org> | 2013-07-07 21:43:23 +0200 |
commit | 636ced8e1dc8248a1353b416240b93d70ad03edb (patch) | |
tree | 6a157f3eb215b97d50fd96ff43d7ae6581a7e9af /cmdutils.c | |
parent | 21732063a346475eb22c332b27e8216b79f9ad4a (diff) | |
download | ffmpeg-636ced8e1dc8248a1353b416240b93d70ad03edb.tar.gz |
cmdutils: wrap exit explicitly
Some C runtime implementations deadlock when calling threading functions
on the atexit() handler.
Use a simpler wrapper similar to av_log to call the cleanup function
before exit.
Bug-Id: 523
Diffstat (limited to 'cmdutils.c')
-rw-r--r-- | cmdutils.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/cmdutils.c b/cmdutils.c index ea86b83415..8e43795191 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -82,6 +82,21 @@ void log_callback_help(void *ptr, int level, const char *fmt, va_list vl) vfprintf(stdout, fmt, vl); } +static void (*program_exit)(int ret); + +void register_exit(void (*cb)(int ret)) +{ + program_exit = cb; +} + +void exit_program(int ret) +{ + if (program_exit) + program_exit(ret); + + exit(ret); +} + double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max) { @@ -99,7 +114,7 @@ double parse_number_or_die(const char *context, const char *numstr, int type, else return d; av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max); - exit(1); + exit_program(1); return 0; } @@ -110,7 +125,7 @@ int64_t parse_time_or_die(const char *context, const char *timestr, if (av_parse_time(&us, timestr, is_duration) < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n", is_duration ? "duration" : "date", context, timestr); - exit(1); + exit_program(1); } return us; } @@ -272,7 +287,7 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, } } if (po->flags & OPT_EXIT) - exit(0); + exit_program(0); return 0; } @@ -332,7 +347,7 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options opt++; if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) - exit(1); + exit_program(1); optindex += ret; } else { if (parse_arg_function) @@ -538,7 +553,7 @@ static void init_parse_context(OptionParseContext *octx, octx->nb_groups = nb_groups; octx->groups = av_mallocz(sizeof(*octx->groups) * octx->nb_groups); if (!octx->groups) - exit(1); + exit_program(1); for (i = 0; i < octx->nb_groups; i++) octx->groups[i].group_def = &groups[i]; @@ -705,7 +720,7 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) "Possible levels are numbers or:\n", arg); for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name); - exit(1); + exit_program(1); } av_log_set_level(level); return 0; @@ -1586,13 +1601,13 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) { if (new_size >= INT_MAX / elem_size) { av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); - exit(1); + exit_program(1); } if (*size < new_size) { uint8_t *tmp = av_realloc(array, new_size*elem_size); if (!tmp) { av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); - exit(1); + exit_program(1); } memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); *size = new_size; |