X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Ftimeval.c;h=6e415147e4047b3e83cf8d06cdbadb0398a7f018;hb=e018053f14beb09ac7f634687c48ac2a214208f2;hp=05f1c2d3643030dc16c20bdcacb44cc0f72311ac;hpb=f43e80e023378a2c1ef18d3caee9b76d6d2a6d23;p=sliver-openvswitch.git diff --git a/lib/timeval.c b/lib/timeval.c index 05f1c2d36..6e415147e 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,7 @@ #include #include "timeval.h" -#include #include -#if HAVE_EXECINFO_H -#include -#endif #include #include #include @@ -39,6 +35,15 @@ #include "util.h" #include "vlog.h" +/* backtrace() from is really useful, but it is not signal safe + * everywhere, such as on x86-64. */ +#if HAVE_EXECINFO_H && !defined __x86_64__ +# define USE_BACKTRACE 1 +# include +#else +# define USE_BACKTRACE 0 +#endif + VLOG_DEFINE_THIS_MODULE(timeval); /* The clock to use for measuring time intervals. This is CLOCK_MONOTONIC by @@ -94,9 +99,7 @@ static void timespec_add(struct timespec *sum, const struct timespec *a, const struct timespec *b); static unixctl_cb_func backtrace_cb; -#ifndef HAVE_EXECINFO_H -#define HAVE_EXECINFO_H 0 - +#if !USE_BACKTRACE static int backtrace(void **buffer OVS_UNUSED, int size OVS_UNUSED) { @@ -108,7 +111,7 @@ backtrace_symbols(void *const *buffer OVS_UNUSED, int size OVS_UNUSED) { NOT_REACHED(); } -#endif +#endif /* !USE_BACKTRACE */ /* Initializes the timetracking module, if not already initialized. */ static void @@ -121,9 +124,19 @@ time_init(void) } inited = true; + /* The implementation of backtrace() in glibc does some one time + * initialization which is not signal safe. This can cause deadlocks if + * run from the signal handler. As a workaround, force the initialization + * to happen here. */ + if (USE_BACKTRACE) { + void *bt[1]; + + backtrace(bt, ARRAY_SIZE(bt)); + } + memset(traces, 0, sizeof traces); - if (HAVE_EXECINFO_H && CACHE_TIME) { + if (USE_BACKTRACE && CACHE_TIME) { unixctl_command_register("backtrace", "", 0, 0, backtrace_cb, NULL); } @@ -319,7 +332,7 @@ time_alarm(unsigned int secs) time_refresh(); now = time_msec(); - msecs = secs * 1000; + msecs = secs * 1000LL; block_sigalrm(&oldsigs); deadline = now < LLONG_MAX - msecs ? now + msecs : LLONG_MAX; @@ -410,7 +423,7 @@ sigalrm_handler(int sig_nr OVS_UNUSED) wall_tick = true; monotonic_tick = true; - if (HAVE_EXECINFO_H && CACHE_TIME) { + if (USE_BACKTRACE && CACHE_TIME) { struct trace *trace = &traces[trace_head]; trace->n_frames = backtrace(trace->backtrace, @@ -507,7 +520,7 @@ log_poll_interval(long long int last_wakeup) { long long int interval = time_msec() - last_wakeup; - if (interval >= 1000) { + if (interval >= 1000 && !warp_offset.tv_sec && !warp_offset.tv_nsec) { const struct rusage *last_rusage = get_recent_rusage(); struct rusage rusage; @@ -624,7 +637,7 @@ format_backtraces(struct ds *ds, size_t min_count) { time_init(); - if (HAVE_EXECINFO_H && CACHE_TIME) { + if (USE_BACKTRACE && CACHE_TIME) { struct hmap trace_map = HMAP_INITIALIZER(&trace_map); struct trace *trace, *next; sigset_t oldsigs; @@ -721,7 +734,7 @@ backtrace_cb(struct unixctl_conn *conn, { struct ds ds = DS_EMPTY_INITIALIZER; - assert(HAVE_EXECINFO_H && CACHE_TIME); + ovs_assert(USE_BACKTRACE && CACHE_TIME); format_backtraces(&ds, 0); unixctl_command_reply(conn, ds_cstr(&ds)); ds_destroy(&ds);