From e0944991973c04701c830647a3f943b43d546b20 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 1 Mar 2016 21:51:59 +0100 Subject: msg: use dynamic buffer for message formatting Until now, a rather large stack buffer was used for this, and also a static buffer in mp_log_root. The latter was added to buffer partial lines, and the stack buffer was used only for MSGL_STATUS and MSGL_STATS (I guess because these are the most likely/severe to clash with partial line buffering). Make the buffer in mp_log_root dynamically sized, so we don't get cut off log lines if the text is excessively large. (The OpenGL extension list dumped by vo_opengl is such an example.) Since we still have to support partial line buffering (FFmpeg's log callbacks leave no other choice), keep the stack buffer. But make it smaller; there's no way all ~6KB are going to be needed in any situation. --- common/msg.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/msg.c b/common/msg.c index 01d0bb78a0..065ef46620 100644 --- a/common/msg.c +++ b/common/msg.c @@ -41,9 +41,6 @@ #include "msg.h" #include "msg_control.h" -/* maximum message length of mp_msg */ -#define MSGSIZE_MAX 6144 - struct mp_log_root { struct mpv_global *global; // --- protected by mp_msg_lock @@ -67,7 +64,7 @@ struct mp_log_root { * synchronized mp_log tree.) */ atomic_ulong reload_counter; // --- protected by mp_msg_lock - char buffer[MSGSIZE_MAX]; + char *buffer; }; struct mp_log { @@ -337,17 +334,27 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va) pthread_mutex_lock(&mp_msg_lock); - char tmp[MSGSIZE_MAX]; + // MSGL_STATUS and MSGL_STATS use their own buffer; this prevents clashes + // with mp_msg() users which do not properly send complete lines only. + char tmp[256]; bool use_tmp = lev == MSGL_STATUS || lev == MSGL_STATS; struct mp_log_root *root = log->root; char *text = use_tmp ? tmp : root->buffer; int len = use_tmp ? 0 : strlen(text); - - if (vsnprintf(text + len, MSGSIZE_MAX - len, format, va) < 0) - snprintf(text + len, MSGSIZE_MAX - len, "[fprintf error]\n"); - text[MSGSIZE_MAX - 2] = '\n'; - text[MSGSIZE_MAX - 1] = 0; + int max_len = use_tmp ? sizeof(tmp) : talloc_get_size(text); + + va_list t; + va_copy(t, va); + int res = vsnprintf(text + len, max_len - len, format, t); + if (res >= 0 && res >= max_len - len && !use_tmp) { + root->buffer = talloc_realloc(root, root->buffer, char, res + len + 1); + text = root->buffer; + max_len = talloc_get_size(text); + res = vsnprintf(text + len, max_len - len, format, va); + } + if (res < 0) + text = "[fprintf error]\n"; if (lev == MSGL_STATS) { dump_stats(log, lev, text); @@ -376,7 +383,7 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va) if (lev == MSGL_STATUS) { if (text[0]) { len = strlen(text); - if (len < MSGSIZE_MAX - 1) { + if (len < max_len - 1) { text[len] = root->termosd ? '\r' : '\n'; text[len + 1] = '\0'; } @@ -441,6 +448,7 @@ void mp_msg_init(struct mpv_global *global) *root = (struct mp_log_root){ .global = global, .reload_counter = ATOMIC_VAR_INIT(1), + .buffer = talloc_strdup(root, ""), }; struct mp_log dummy = { .root = root }; -- cgit v1.2.3