From db8f10cfa160818681eebd2169cd11553760028b Mon Sep 17 00:00:00 2001 From: Mike Brady Date: Tue, 17 Sep 2019 12:14:55 +0100 Subject: [PATCH] add the option (normally on) of including the file name and line number of the originrating message in a debug log message --- common.c | 222 ++++++++++++++++++++++-------------- common.h | 45 ++++++-- dbus-service.c | 26 +++++ org.gnome.ShairportSync.xml | 1 + scripts/shairport-sync.conf | 3 +- shairport.c | 13 +++ 6 files changed, 216 insertions(+), 94 deletions(-) diff --git a/common.c b/common.c index 0fa2c1584..2cadc2031 100644 --- a/common.c +++ b/common.c @@ -87,6 +87,11 @@ void set_alsa_out_dev(char *); #endif +// always lock use this when accessing the fp_time_at_last_debug_message +static pthread_mutex_t debug_timing_lock = PTHREAD_MUTEX_INITIALIZER; + +pthread_mutex_t the_conn_lock = PTHREAD_MUTEX_INITIALIZER; + const char *sps_format_description_string_array[] = { "unknown", "S8", "U8", "S16", "S16_LE", "S16_BE", "S24", "S24_LE", "S24_BE", "S24_3LE", "S24_3BE", "S32", "S32_LE", "S32_BE", "auto", "invalid"}; @@ -124,6 +129,21 @@ void log_to_stderr() { sps_log = do_sps_log; } shairport_cfg config; +// accessors for multi-thread-access fields in the conn structure + +double get_config_airplay_volume() { + config_lock; + double v = config.airplay_volume; + config_unlock; + return v; +} + +void set_config_airplay_volume(double v) { + config_lock; + config.airplay_volume = v; + config_unlock; +} + volatile int debuglev = 0; sigset_t pselect_sigset; @@ -159,115 +179,140 @@ int get_requested_connection_state_to_output() { return requested_connection_sta void set_requested_connection_state_to_output(int v) { requested_connection_state_to_output = v; } -void die(const char *format, ...) { +char *generate_preliminary_string(char *buffer, size_t buffer_length, double tss, double tsl, + const char *filename, const int linenumber, const char *prefix) { + size_t space_remaining = buffer_length; + char *insertion_point = buffer; + if (config.debugger_show_elapsed_time) { + snprintf(insertion_point, space_remaining, "% 20.9f", tss); + insertion_point = insertion_point + strlen(insertion_point); + space_remaining = space_remaining - strlen(insertion_point); + } + if (config.debugger_show_relative_time) { + snprintf(insertion_point, space_remaining, "% 20.9f", tsl); + insertion_point = insertion_point + strlen(insertion_point); + space_remaining = space_remaining - strlen(insertion_point); + } + if (config.debugger_show_file_and_line) { + snprintf(insertion_point, space_remaining, " \"%s:%d\"", filename, linenumber); + insertion_point = insertion_point + strlen(insertion_point); + space_remaining = space_remaining - strlen(insertion_point); + } + + if (prefix) { + snprintf(insertion_point, space_remaining, "%s", prefix); + insertion_point = insertion_point + strlen(insertion_point); + } + return insertion_point; +} + +void _die(const char *filename, const int linenumber, const char *format, ...) { int oldState; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); - char s[1024]; - s[0] = 0; - uint64_t time_now = get_absolute_time_in_fp(); - uint64_t time_since_start = time_now - fp_time_at_startup; - uint64_t time_since_last_debug_message = time_now - fp_time_at_last_debug_message; - fp_time_at_last_debug_message = time_now; - uint64_t divisor = (uint64_t)1 << 32; - double tss = 1.0 * time_since_start / divisor; - double tsl = 1.0 * time_since_last_debug_message / divisor; + char b[1024]; + b[0] = 0; + char *s; + if (debuglev) { + pthread_mutex_lock(&debug_timing_lock); + uint64_t time_now = get_absolute_time_in_fp(); + uint64_t time_since_start = time_now - fp_time_at_startup; + uint64_t time_since_last_debug_message = time_now - fp_time_at_last_debug_message; + fp_time_at_last_debug_message = time_now; + pthread_mutex_unlock(&debug_timing_lock); + uint64_t divisor = (uint64_t)1 << 32; + s = generate_preliminary_string(b, sizeof(b), 1.0 * time_since_start / divisor, + 1.0 * time_since_last_debug_message / divisor, filename, + linenumber, " *fatal error: "); + } else { + s = b; + } va_list args; va_start(args, format); - vsnprintf(s, sizeof(s), format, args); + vsnprintf(s, sizeof(b) - (s - b), format, args); va_end(args); - - if ((debuglev) && (config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - sps_log(LOG_ERR, "|% 20.9f|% 20.9f|*fatal error: %s", tss, tsl, s); - else if ((debuglev) && (config.debugger_show_relative_time)) - sps_log(LOG_ERR, "% 20.9f|*fatal error: %s", tsl, s); - else if ((debuglev) && (config.debugger_show_elapsed_time)) - sps_log(LOG_ERR, "% 20.9f|*fatal error: %s", tss, s); - else - sps_log(LOG_ERR, "fatal error: %s", s); + sps_log(LOG_ERR, "%s", b); pthread_setcancelstate(oldState, NULL); abort(); // exit() doesn't always work, by heaven. } -void warn(const char *format, ...) { +void _warn(const char *filename, const int linenumber, const char *format, ...) { int oldState; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); - char s[1024]; - s[0] = 0; - uint64_t time_now = get_absolute_time_in_fp(); - uint64_t time_since_start = time_now - fp_time_at_startup; - uint64_t time_since_last_debug_message = time_now - fp_time_at_last_debug_message; - fp_time_at_last_debug_message = time_now; - uint64_t divisor = (uint64_t)1 << 32; - double tss = 1.0 * time_since_start / divisor; - double tsl = 1.0 * time_since_last_debug_message / divisor; + char b[1024]; + b[0] = 0; + char *s; + if (debuglev) { + pthread_mutex_lock(&debug_timing_lock); + uint64_t time_now = get_absolute_time_in_fp(); + uint64_t time_since_start = time_now - fp_time_at_startup; + uint64_t time_since_last_debug_message = time_now - fp_time_at_last_debug_message; + fp_time_at_last_debug_message = time_now; + pthread_mutex_unlock(&debug_timing_lock); + uint64_t divisor = (uint64_t)1 << 32; + s = generate_preliminary_string(b, sizeof(b), 1.0 * time_since_start / divisor, + 1.0 * time_since_last_debug_message / divisor, filename, + linenumber, " *warning: "); + } else { + s = b; + } va_list args; va_start(args, format); - vsnprintf(s, sizeof(s), format, args); + vsnprintf(s, sizeof(b) - (s - b), format, args); va_end(args); - if ((debuglev) && (config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - sps_log(LOG_WARNING, "|% 20.9f|% 20.9f|*warning: %s", tss, tsl, s); - else if ((debuglev) && (config.debugger_show_relative_time)) - sps_log(LOG_WARNING, "% 20.9f|*warning: %s", tsl, s); - else if ((debuglev) && (config.debugger_show_elapsed_time)) - sps_log(LOG_WARNING, "% 20.9f|*warning: %s", tss, s); - else - sps_log(LOG_WARNING, "%s", s); + sps_log(LOG_WARNING, "%s", b); pthread_setcancelstate(oldState, NULL); } -void debug(int level, const char *format, ...) { +void _debug(const char *filename, const int linenumber, int level, const char *format, ...) { if (level > debuglev) return; int oldState; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); - char s[1024]; - s[0] = 0; + char b[1024]; + b[0] = 0; + pthread_mutex_lock(&debug_timing_lock); uint64_t time_now = get_absolute_time_in_fp(); uint64_t time_since_start = time_now - fp_time_at_startup; uint64_t time_since_last_debug_message = time_now - fp_time_at_last_debug_message; fp_time_at_last_debug_message = time_now; + pthread_mutex_unlock(&debug_timing_lock); uint64_t divisor = (uint64_t)1 << 32; - double tss = 1.0 * time_since_start / divisor; - double tsl = 1.0 * time_since_last_debug_message / divisor; + char *s = generate_preliminary_string(b, sizeof(b), 1.0 * time_since_start / divisor, + 1.0 * time_since_last_debug_message / divisor, filename, + linenumber, " "); va_list args; va_start(args, format); - vsnprintf(s, sizeof(s), format, args); + vsnprintf(s, sizeof(b) - (s - b), format, args); va_end(args); - if ((config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - sps_log(LOG_DEBUG, "|% 20.9f|% 20.9f|%s", tss, tsl, s); - else if (config.debugger_show_relative_time) - sps_log(LOG_DEBUG, "% 20.9f|%s", tsl, s); - else if (config.debugger_show_elapsed_time) - sps_log(LOG_DEBUG, "% 20.9f|%s", tss, s); - else - sps_log(LOG_DEBUG, "%s", s); + sps_log(LOG_DEBUG, "%s", b); pthread_setcancelstate(oldState, NULL); } -void inform(const char *format, ...) { +void _inform(const char *filename, const int linenumber, const char *format, ...) { int oldState; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); - char s[1024]; - s[0] = 0; - uint64_t time_now = get_absolute_time_in_fp(); - uint64_t time_since_start = time_now - fp_time_at_startup; - uint64_t time_since_last_debug_message = time_now - fp_time_at_last_debug_message; - fp_time_at_last_debug_message = time_now; - uint64_t divisor = (uint64_t)1 << 32; - double tss = 1.0 * time_since_start / divisor; - double tsl = 1.0 * time_since_last_debug_message / divisor; + char b[1024]; + b[0] = 0; + char *s; + if (debuglev) { + pthread_mutex_lock(&debug_timing_lock); + uint64_t time_now = get_absolute_time_in_fp(); + uint64_t time_since_start = time_now - fp_time_at_startup; + uint64_t time_since_last_debug_message = time_now - fp_time_at_last_debug_message; + fp_time_at_last_debug_message = time_now; + pthread_mutex_unlock(&debug_timing_lock); + uint64_t divisor = (uint64_t)1 << 32; + s = generate_preliminary_string(b, sizeof(b), 1.0 * time_since_start / divisor, + 1.0 * time_since_last_debug_message / divisor, filename, + linenumber, " "); + } else { + s = b; + } va_list args; va_start(args, format); - vsnprintf(s, sizeof(s), format, args); + vsnprintf(s, sizeof(b) - (s - b), format, args); va_end(args); - if ((debuglev) && (config.debugger_show_elapsed_time) && (config.debugger_show_relative_time)) - sps_log(LOG_INFO, "|% 20.9f|% 20.9f|%s", tss, tsl, s); - else if ((debuglev) && (config.debugger_show_relative_time)) - sps_log(LOG_INFO, "% 20.9f|%s", tsl, s); - else if ((debuglev) && (config.debugger_show_elapsed_time)) - sps_log(LOG_INFO, "% 20.9f|%s", tss, s); - else - sps_log(LOG_INFO, "%s", s); + sps_log(LOG_INFO, "%s", b); pthread_setcancelstate(oldState, NULL); } @@ -862,17 +907,17 @@ double flat_vol2attn(double vol, long max_db, long min_db) { double vol2attn(double vol, long max_db, long min_db) { -// We use a little coordinate geometry to build a transfer function from the volume passed in to -// the device's dynamic range. (See the diagram in the documents folder.) The x axis is the -// "volume in" which will be from -30 to 0. The y axis will be the "volume out" which will be from -// the bottom of the range to the top. We build the transfer function from one or more lines. We -// characterise each line with two numbers: the first is where on x the line starts when y=0 (x -// can be from 0 to -30); the second is where on y the line stops when when x is -30. thus, if the -// line was characterised as {0,-30}, it would be an identity transfer. Assuming, for example, a -// dynamic range of lv=-60 to hv=0 Typically we'll use three lines -- a three order transfer -// function First: {0,30} giving a gentle slope -- the 30 comes from half the dynamic range -// Second: {-5,-30-(lv+30)/2} giving a faster slope from y=0 at x=-12 to y=-42.5 at x=-30 -// Third: {-17,lv} giving a fast slope from y=0 at x=-19 to y=-60 at x=-30 + // We use a little coordinate geometry to build a transfer function from the volume passed in to + // the device's dynamic range. (See the diagram in the documents folder.) The x axis is the + // "volume in" which will be from -30 to 0. The y axis will be the "volume out" which will be from + // the bottom of the range to the top. We build the transfer function from one or more lines. We + // characterise each line with two numbers: the first is where on x the line starts when y=0 (x + // can be from 0 to -30); the second is where on y the line stops when when x is -30. thus, if the + // line was characterised as {0,-30}, it would be an identity transfer. Assuming, for example, a + // dynamic range of lv=-60 to hv=0 Typically we'll use three lines -- a three order transfer + // function First: {0,30} giving a gentle slope -- the 30 comes from half the dynamic range + // Second: {-5,-30-(lv+30)/2} giving a faster slope from y=0 at x=-12 to y=-42.5 at x=-30 + // Third: {-17,lv} giving a fast slope from y=0 at x=-19 to y=-60 at x=-30 #define order 3 @@ -1044,6 +1089,9 @@ char *str_replace(const char *string, const char *substr, const char *replacemen /* from http://burtleburtle.net/bob/rand/smallprng.html */ +// this is not thread-safe, so we need a mutex on it to use it properly// always lock use this when accessing the fp_time_at_last_debug_message +pthread_mutex_t r64_mutex = PTHREAD_MUTEX_INITIALIZER; + // typedef uint64_t u8; typedef struct ranctx { uint64_t a; @@ -1157,8 +1205,9 @@ int sps_pthread_mutex_timedlock(pthread_mutex_t *mutex, useconds_t dally_time, et = (et * 1000000) >> 32; // microseconds char errstr[1000]; if (r == ETIMEDOUT) - debug(debuglevel, "timed out waiting for a mutex, having waiting %f seconds, with a maximum " - "waiting time of %d microseconds. \"%s\".", + debug(debuglevel, + "timed out waiting for a mutex, having waiting %f seconds, with a maximum " + "waiting time of %d microseconds. \"%s\".", (1.0 * et) / 1000000, dally_time, debugmessage); else debug(debuglevel, "error %d: \"%s\" waiting for a mutex: \"%s\".", r, @@ -1388,10 +1437,10 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma int64_t previous_random_number = random_number_in; char *p = outp; size_t sample_number; + r64_lock; // the random number generator is not thread safe, so we need to lock it while using it for (sample_number = 0; sample_number < number_of_frames * 2; sample_number++) { int64_t hyper_sample = 0; - int64_t r = r64i(); int64_t tpdf = (r & dither_mask) - (previous_random_number & dither_mask); @@ -1485,6 +1534,7 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma p += sample_length; previous_random_number = r; } + r64_unlock; return previous_random_number; } diff --git a/common.h b/common.h index 96b2f8170..2bb2ec098 100644 --- a/common.h +++ b/common.h @@ -100,6 +100,7 @@ enum sps_format_t { const char *sps_format_description_string(enum sps_format_t format); typedef struct { + pthread_mutex_t lock; config_t *cfg; int endianness; double airplay_volume; // stored here for reloading when necessary @@ -148,13 +149,13 @@ typedef struct { int volume_max_db; int no_sync; // disable synchronisation, even if it's available int no_mmap; // disable use of mmap-based output, even if it's available - double resyncthreshold; // if it gets out of whack my more than this number of seconds, resync. + double resyncthreshold; // if it get's out of whack my more than this number of seconds, resync. // Zero means never // resync. int allow_session_interruption; int timeout; // while in play mode, exit if no packets of audio come in for more than this number // of seconds . Zero means never exit. - int dont_check_timeout; // this is used to maintain backward compatibility with the old -t option + int dont_check_timeout; // this is used to maintain backward compatability with the old -t option // behaviour; only set by -t 0, cleared by everything else char *output_name; audio_output *output; @@ -176,6 +177,7 @@ typedef struct { int logOutputLevel; // log output level int debugger_show_elapsed_time; // in the debug message, display the time since startup int debugger_show_relative_time; // in the debug message, display the time since the last one + int debugger_show_file_and_line; // in the debug message, display the filename and line number int statistics_requested, use_negotiated_latencies; enum playback_mode_type playback_mode; char *cmd_start, *cmd_stop, *cmd_set_volume, *cmd_unfixable; @@ -194,7 +196,7 @@ typedef struct { char *configfile; char *regtype; // The regtype is the service type followed by the protocol, separated by a dot, by // default “_raop._tcp.”. - char *interface; // a string containing the interface name, or NULL if nothing specified + char *interface; // a string containg the interface name, or NULL if nothing specified int interface_index; // only valid if the interface string is non-NULL double audio_backend_buffer_desired_length; // this will be the length in seconds of the // audio backend buffer -- the DAC buffer for ALSA @@ -266,6 +268,10 @@ typedef struct { } shairport_cfg; +// accessors to config for multi-thread access +double get_config_airplay_volume(); +void set_config_airplay_volume(double v); + uint32_t nctohl(const uint8_t *p); // read 4 characters from *p and do ntohl on them uint16_t nctohs(const uint8_t *p); // read 2 characters from *p and do ntohs on them @@ -308,10 +314,15 @@ uint16_t nextFreeUDPPort(); volatile int debuglev; -void die(const char *format, ...); -void warn(const char *format, ...); -void inform(const char *format, ...); -void debug(int level, const char *format, ...); +void _die(const char *filename, const int linenumber, const char *format, ...); +void _warn(const char *filename, const int linenumber, const char *format, ...); +void _inform(const char *filename, const int linenumber, const char *format, ...); +void _debug(const char *filename, const int linenumber, int level, const char *format, ...); + +#define die(...) _die(__FILE__, __LINE__, __VA_ARGS__) +#define debug(...) _debug(__FILE__, __LINE__, __VA_ARGS__) +#define warn(...) _warn(__FILE__, __LINE__, __VA_ARGS__) +#define inform(...) _inform(__FILE__, __LINE__, __VA_ARGS__) uint8_t *base64_dec(char *input, int *outlen); char *base64_enc(uint8_t *input, int length); @@ -357,6 +368,13 @@ void shairport_shutdown(); extern sigset_t pselect_sigset; +pthread_mutex_t the_conn_lock; + +#define conn_lock(arg) \ + pthread_mutex_lock(&the_conn_lock); \ + arg; \ + pthread_mutex_unlock(&the_conn_lock); + // wait for the specified time in microseconds -- it checks every 20 milliseconds int sps_pthread_mutex_timedlock(pthread_mutex_t *mutex, useconds_t dally_time, const char *debugmessage, int debuglevel); @@ -378,6 +396,19 @@ void pthread_cleanup_debug_mutex_unlock(void *arg); if (_debug_mutex_lock(mu, t, #mu, __FILE__, __LINE__, d) == 0) \ pthread_cleanup_push(pthread_cleanup_debug_mutex_unlock, (void *)mu) +#define config_lock \ + if (pthread_mutex_trylock(&config.lock) != 0) { \ + debug(1, "config_lock: cannot acquire config.lock"); \ + } + +#define config_unlock pthread_mutex_unlock(&config.lock) + +pthread_mutex_t r64_mutex; + +#define r64_lock pthread_mutex_lock(&r64_mutex) + +#define r64_unlock pthread_mutex_unlock(&r64_mutex) + char *get_version_string(); // mallocs a string space -- remember to free it afterwards void sps_nanosleep(const time_t sec, diff --git a/dbus-service.c b/dbus-service.c index 2393675b7..76cc04564 100644 --- a/dbus-service.c +++ b/dbus-service.c @@ -359,6 +359,19 @@ gboolean notify_delta_time_callback(ShairportSyncDiagnostics *skeleton, return TRUE; } +gboolean notify_file_and_line_callback(ShairportSyncDiagnostics *skeleton, + __attribute__((unused)) gpointer user_data) { + // debug(1, "\"notify_file_and_line_callback\" called."); + if (shairport_sync_diagnostics_get_file_and_line(skeleton)) { + config.debugger_show_file_and_line = 1; + debug(1, ">> start including file and line in logs"); + } else { + config.debugger_show_file_and_line = 0; + debug(1, ">> stop including file and line in logs"); + } + return TRUE; +} + gboolean notify_statistics_callback(ShairportSyncDiagnostics *skeleton, __attribute__((unused)) gpointer user_data) { // debug(1, "\"notify_statistics_callback\" called."); @@ -698,6 +711,9 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name g_signal_connect(shairportSyncDiagnosticsSkeleton, "notify::delta-time", G_CALLBACK(notify_delta_time_callback), NULL); + g_signal_connect(shairportSyncDiagnosticsSkeleton, "notify::file-and-line", + G_CALLBACK(notify_file_and_line_callback), NULL); + g_signal_connect(shairportSyncRemoteControlSkeleton, "handle-fast-forward", G_CALLBACK(on_handle_fast_forward), NULL); g_signal_connect(shairportSyncRemoteControlSkeleton, "handle-rewind", @@ -854,6 +870,16 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name // debug(1, ">> delta time is not included in log entries"); } + if (config.debugger_show_file_and_line == 0) { + shairport_sync_diagnostics_set_file_and_line( + SHAIRPORT_SYNC_DIAGNOSTICS(shairportSyncDiagnosticsSkeleton), FALSE); + // debug(1, ">> file and line is included in log entries"); + } else { + shairport_sync_diagnostics_set_file_and_line( + SHAIRPORT_SYNC_DIAGNOSTICS(shairportSyncDiagnosticsSkeleton), TRUE); + // debug(1, ">> file and line is not included in log entries"); + } + shairport_sync_remote_control_set_player_state(shairportSyncRemoteControlSkeleton, "Not Available"); shairport_sync_advanced_remote_control_set_playback_status( diff --git a/org.gnome.ShairportSync.xml b/org.gnome.ShairportSync.xml index cea574bcb..e4a7d1e6f 100644 --- a/org.gnome.ShairportSync.xml +++ b/org.gnome.ShairportSync.xml @@ -22,6 +22,7 @@ + diff --git a/scripts/shairport-sync.conf b/scripts/shairport-sync.conf index 5e6089aa7..6bca6d0e1 100644 --- a/scripts/shairport-sync.conf +++ b/scripts/shairport-sync.conf @@ -96,7 +96,7 @@ alsa = // disable_standby_mode_silence_threshold = 0.040; // Use this optional advanced setting to control how little audio should remain in the output buffer before the disable_standby code should start sending silence to the output device. // disable_standby_mode_silence_scan_interval = 0.004; // Use this optional advanced setting to control how often the amount of audio remaining in the output buffer should be checked. }; - +G // Parameters for the "sndio" audio back end. All are optional. // For this section to be operative, Shairport Sync must be built with the following configuration flag: // --with-sndio @@ -224,6 +224,7 @@ diagnostics = // disable_resend_requests = "no"; // set this to yes to stop Shairport Sync from requesting the retransmission of missing packets. Default is "no". // statistics = "no"; // set to "yes" to print statistics in the log // log_verbosity = 0; // "0" means no debug verbosity, "3" is most verbose. +// log_show_file_and_line = "yes"; // set this to yes if you want the file and line number of the message source in the log file // log_show_time_since_startup = "no"; // set this to yes if you want the time since startup in the debug message -- seconds down to nanoseconds // log_show_time_since_last_message = "yes"; // set this to yes if you want the time since the last debug message in the debug message -- seconds down to nanoseconds // drop_this_fraction_of_audio_packets = 0.0; // use this to simulate a noisy network where this fraction of UDP packets are lost in transmission. E.g. a value of 0.001 would mean an average of 0.1% of packets are lost, which is actually quite a high figure. diff --git a/shairport.c b/shairport.c index 54647976c..603446f08 100644 --- a/shairport.c +++ b/shairport.c @@ -576,6 +576,17 @@ int parse_options(int argc, char **argv) { value); } + /* Get the config.debugger_show_file_and_line in debug messages setting. */ + if (config_lookup_string(config.cfg, "diagnostics.log_show_file_and_line", &str)) { + if (strcasecmp(str, "no") == 0) + config.debugger_show_file_and_line = 0; + else if (strcasecmp(str, "yes") == 0) + config.debugger_show_file_and_line = 1; + else + die("Invalid diagnostics log_show_file_and_line option choice \"%s\". It should be " + "\"yes\" or \"no\""); + } + /* Get the show elapsed time in debug messages setting. */ if (config_lookup_string(config.cfg, "diagnostics.log_show_time_since_startup", &str)) { if (strcasecmp(str, "no") == 0) @@ -1365,6 +1376,8 @@ int main(int argc, char **argv) { // config.statistics_requested = 0; // don't print stats in the log // config.userSuppliedLatency = 0; // zero means none supplied + config.debugger_show_file_and_line = + 1; // by default, log the file and line of the originating message config.debugger_show_relative_time = 1; // by default, log the time back to the previous debug message config.resyncthreshold = 0.05; // 50 ms