Added support for early and late calls to Vstr wrappers.

That is, prevent a SIGSEGV if Vstr wrappers are called before printf_hook_t
is initialized and after it is destroyed.
This commit is contained in:
Tobias Brunner
2010-08-10 13:00:20 +02:00
parent 478eb66030
commit 6432669fa2
+50 -21
View File
@@ -132,6 +132,14 @@ static int custom_arginfo(const struct printf_info *info, size_t n, int *argtype
#include <errno.h> #include <errno.h>
#include <unistd.h> /* for STDOUT_FILENO */ #include <unistd.h> /* for STDOUT_FILENO */
/**
* These are used below, whenever the public wrapper functions are called before
* initialization or after destruction.
*/
#undef vprintf
#undef vfprintf
#undef vsnprintf
/** /**
* Vstr custom format specifier callback function. * Vstr custom format specifier callback function.
*/ */
@@ -177,13 +185,16 @@ static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler
switch(handler->numargs) switch(handler->numargs)
{ {
case 1: case 1:
vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0], VSTR_TYPE_FMT_END); vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
VSTR_TYPE_FMT_END);
break; break;
case 2: case 2:
vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0], at[1], VSTR_TYPE_FMT_END); vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
at[1], VSTR_TYPE_FMT_END);
break; break;
case 3: case 3:
vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0], at[1], at[2], VSTR_TYPE_FMT_END); vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
at[1], at[2], VSTR_TYPE_FMT_END);
break; break;
} }
} }
@@ -193,7 +204,7 @@ static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler
*/ */
#include <threading/thread_value.h> #include <threading/thread_value.h>
static thread_value_t *vstr_conf; static thread_value_t *vstr_conf = NULL;
static Vstr_conf *create_vstr_conf() static Vstr_conf *create_vstr_conf()
{ {
@@ -216,12 +227,15 @@ static Vstr_conf *create_vstr_conf()
static inline Vstr_conf *get_vstr_conf() static inline Vstr_conf *get_vstr_conf()
{ {
Vstr_conf *conf; Vstr_conf *conf = NULL;
conf = (Vstr_conf*)vstr_conf->get(vstr_conf); if (vstr_conf)
if (!conf)
{ {
conf = create_vstr_conf(); conf = (Vstr_conf*)vstr_conf->get(vstr_conf);
vstr_conf->set(vstr_conf, conf); if (!conf)
{
conf = create_vstr_conf();
vstr_conf->set(vstr_conf, conf);
}
} }
return conf; return conf;
} }
@@ -274,11 +288,11 @@ int vstr_wrapper_asprintf(char **str, const char *format, ...)
va_end(args); va_end(args);
return written; return written;
} }
static inline int vstr_wrapper_vprintf_internal(int fd, const char *format, static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, int fd,
const char *format,
va_list args) va_list args)
{ {
int written; int written;
Vstr_conf *conf = get_vstr_conf();
Vstr_base *s = vstr_make_base(conf); Vstr_base *s = vstr_make_base(conf);
vstr_add_vfmt(s, 0, format, args); vstr_add_vfmt(s, 0, format, args);
written = s->len; written = s->len;
@@ -298,24 +312,39 @@ static inline int vstr_wrapper_vprintf_internal(int fd, const char *format,
} }
int vstr_wrapper_vprintf(const char *format, va_list args) int vstr_wrapper_vprintf(const char *format, va_list args)
{ {
return vstr_wrapper_vprintf_internal(STDOUT_FILENO, format, args); Vstr_conf *conf = get_vstr_conf();
if (conf)
{
return vstr_wrapper_vprintf_internal(conf, STDOUT_FILENO, format, args);
}
return vprintf(format, args);
} }
int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list args) int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list args)
{ {
return vstr_wrapper_vprintf_internal(fileno(stream), format, args); Vstr_conf *conf = get_vstr_conf();
if (conf)
{
return vstr_wrapper_vprintf_internal(conf, fileno(stream), format,
args);
}
return vfprintf(stream, format, args);
} }
static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size, static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size,
const char *format, const char *format,
va_list args) va_list args)
{ {
int written;
Vstr_conf *conf = get_vstr_conf(); Vstr_conf *conf = get_vstr_conf();
Vstr_base *s = vstr_make_base(conf); if (conf)
vstr_add_vfmt(s, 0, format, args); {
written = s->len; int written;
vstr_export_cstr_buf(s, 1, s->len, str, (size > 0) ? size : s->len + 1); Vstr_base *s = vstr_make_base(conf);
vstr_free_base(s); vstr_add_vfmt(s, 0, format, args);
return written; written = s->len;
vstr_export_cstr_buf(s, 1, s->len, str, (size > 0) ? size : s->len + 1);
vstr_free_base(s);
return written;
}
return vsnprintf(str, size, format, args);
} }
int vstr_wrapper_vsprintf(char *str, const char *format, va_list args) int vstr_wrapper_vsprintf(char *str, const char *format, va_list args)
{ {
@@ -346,7 +375,6 @@ int vstr_wrapper_vasprintf(char **str, const char *format, va_list args)
} }
return written; return written;
} }
#endif #endif
/** /**
@@ -437,6 +465,7 @@ static void destroy(private_printf_hook_t *this)
#ifdef USE_VSTR #ifdef USE_VSTR
/* freeing the Vstr_conf of the main thread */ /* freeing the Vstr_conf of the main thread */
vstr_conf->destroy(vstr_conf); vstr_conf->destroy(vstr_conf);
vstr_conf = NULL;
vstr_free_conf(conf); vstr_free_conf(conf);
vstr_exit(); vstr_exit();
#endif #endif