From: Harald Hoyer <har...@redhat.com> use stack_size_guess() to get rid of LINE_MAX --- src/journal/journal-send.c | 99 +++++++++++++++++++++++++++++++---------- src/journal/test-journal-send.c | 92 +++++++++++++++++++++++++++++++++----- 2 files changed, 156 insertions(+), 35 deletions(-)
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index 4b9109a..2ff04b4 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -26,6 +26,7 @@ #include <unistd.h> #include <fcntl.h> #include <printf.h> +#include <sys/resource.h> #define SD_JOURNAL_SUPPRESS_LOCATION @@ -35,15 +36,17 @@ #define SNDBUF_SIZE (8*1024*1024) -#define ALLOCA_CODE_FUNC(f, func) \ - do { \ - size_t _fl; \ - const char *_func = (func); \ - char **_f = &(f); \ - _fl = strlen(_func) + 1; \ - *_f = alloca(_fl + 10); \ - memcpy(*_f, "CODE_FUNC=", 10); \ - memcpy(*_f + 10, _func, _fl); \ +#define ALLOCA_CODE_FUNC(f, func) \ + do { \ + size_t _fl; \ + const char *_func = (func); \ + char **_f = &(f); \ + _fl = strlen(_func) + 1; \ + if (stack_size_guess() < (_fl + 10)) \ + return -ENOMEM; \ + *_f = alloca(_fl + 10); \ + memcpy(*_f, "CODE_FUNC=", 10); \ + memcpy(*_f + 10, _func, _fl); \ } while(false) /* We open a single fd, and we'll share it with the current process, @@ -85,11 +88,9 @@ _public_ int sd_journal_print(int priority, const char *format, ...) { } _public_ int sd_journal_printv(int priority, const char *format, va_list ap) { - - /* FIXME: Instead of limiting things to LINE_MAX we could do a - C99 variable-length array on the stack here in a loop. */ - - char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2]; + char p[11], *buffer; struct iovec iov[2]; + int len = 0; + rlim_t sts = RLIM_INFINITY; if (priority < 0 || priority > 7) return -EINVAL; @@ -97,12 +98,37 @@ _public_ int sd_journal_printv(int priority, const char *format, va_list ap) { if (!format) return -EINVAL; - snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK); - char_array_0(p); + { + va_list aq; + va_copy(aq, ap); + len = vsnprintf(NULL, 0, format, aq); + va_end(aq); + } + if (len <= 0) + return -EINVAL; + + sts = stack_size_guess(); + + /* Limit the maximum size to the send buffer minus some + bytes for the rest + */ + if (sts == RLIM_INFINITY) + sts = SNDBUF_SIZE - 1024; + + /* Spare at least one page_size of stack */ + if (sts < (unsigned)(len + page_size())) + len = sts - page_size(); + + if (len < 0) + return -ENOMEM; + + buffer = alloca(len + 9); memcpy(buffer, "MESSAGE=", 8); - vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap); - char_array_0(buffer); + vsnprintf(buffer+8, len+1, format, ap); + + snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK); + char_array_0(p); zero(iov); IOVEC_SET_STRING(iov[0], buffer); @@ -478,9 +504,11 @@ _public_ int sd_journal_print_with_location(int priority, const char *file, cons } _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) { - char buffer[8 + LINE_MAX], p[11]; + char p[11], *buffer = NULL; struct iovec iov[5]; char *f; + int len = 0; + rlim_t sts = RLIM_INFINITY; if (priority < 0 || priority > 7) return -EINVAL; @@ -488,12 +516,37 @@ _public_ int sd_journal_printv_with_location(int priority, const char *file, con if (_unlikely_(!format)) return -EINVAL; - snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK); - char_array_0(p); + { + va_list aq; + va_copy(aq, ap); + len = vsnprintf(NULL, 0, format, aq); + va_end(aq); + } + if (len <= 0) + return -EINVAL; + + sts = stack_size_guess(); + + /* Limit the maximum size to the send buffer minus some + bytes for the rest + */ + if (sts == RLIM_INFINITY) + sts = SNDBUF_SIZE - 1024; + + /* Spare at least one page_size of stack */ + if (sts < (unsigned)(len + page_size())) + len = sts - page_size(); + + if (len < 0) + return -ENOMEM; + + buffer = alloca(len + 9); memcpy(buffer, "MESSAGE=", 8); - vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap); - char_array_0(buffer); + vsnprintf(buffer+8, len+1, format, ap); + + snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK); + char_array_0(p); /* func is initialized from __func__ which is not a macro, but * a static const char[], hence cannot easily be prefixed with diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c index 3e986ed..b2ff422 100644 --- a/src/journal/test-journal-send.c +++ b/src/journal/test-journal-send.c @@ -22,34 +22,66 @@ #include <systemd/sd-journal.h> #include <stdlib.h> #include <unistd.h> - +#include <stdio.h> +#include <sys/resource.h> #include "log.h" +#define HUGE_SIZE (4096*1024) + +static int huge_message_send(void) +{ + char *huge; + int r; + int asz = random() % (long int)sysconf(_SC_PAGESIZE); + huge = alloca(asz); + memset(huge, 'x', asz-1); + huge[asz-1] = 0; + r = sd_journal_print(LOG_NOTICE, "huge_message_send: %s", huge); + if (r) + return r; + + r = huge_message_send(); + return r; +} + + int main(int argc, char *argv[]) { - char huge[4096*1024]; + int r; + char huge[HUGE_SIZE]; + struct rlimit rlim; log_set_max_level(LOG_DEBUG); - sd_journal_print(LOG_INFO, "piepapo"); + r = sd_journal_print(LOG_INFO, "piepapo"); + if (r != 0) + return 1; - sd_journal_send("MESSAGE=foobar", + r = sd_journal_send("MESSAGE=foobar", "VALUE=%i", 7, NULL); + if (r != 0) + return 1; errno = ENOENT; - sd_journal_perror("Foobar"); + r = sd_journal_perror("Foobar"); + if (r != 0) + return 1; - sd_journal_perror(""); + r = sd_journal_perror(""); + if (r != 0) + return 1; memset(huge, 'x', sizeof(huge)); memcpy(huge, "HUGE=", 5); char_array_0(huge); - sd_journal_send("MESSAGE=Huge field attached", + r = sd_journal_send("MESSAGE=Huge field attached", huge, NULL); + if (r != 0) + return 1; - sd_journal_send("MESSAGE=uiui", + r = sd_journal_send("MESSAGE=uiui", "VALUE=A", "VALUE=B", "VALUE=C", @@ -58,12 +90,16 @@ int main(int argc, char *argv[]) { "OTHERVALUE=Y", "WITH_BINARY=this is a binary value \a", NULL); + if (r != 0) + return 1; syslog(LOG_NOTICE, "Hello World!"); - sd_journal_print(LOG_NOTICE, "Hello World"); + r = sd_journal_print(LOG_NOTICE, "Hello World!"); + if (r != 0) + return 1; - sd_journal_send("MESSAGE=Hello World!", + r = sd_journal_send("MESSAGE=Hello World!", "MESSAGE_ID=52fb62f99e2c49d89cfbf9d6de5e3555", "PRIORITY=5", "HOME=%s", getenv("HOME"), @@ -71,8 +107,40 @@ int main(int argc, char *argv[]) { "PAGE_SIZE=%li", sysconf(_SC_PAGESIZE), "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN), NULL); - - sleep(10); + if (r != 0) + return 1; + + r = sd_journal_print(LOG_NOTICE, "huge string: %s", huge); + if (r != 0) + return 1; + + r = getrlimit(RLIMIT_STACK, &rlim); + if (r) { + perror("getrlimit"); + return 1; + } + + rlim.rlim_cur = (rlim_t)sysconf(_SC_PAGESIZE) * 100; + r = setrlimit(RLIMIT_STACK, &rlim); + if (r) { + perror("setrlimit"); + return 1; + } + + r = sd_journal_print(LOG_NOTICE, "huge string: %s", huge); + if (r != -ENOMEM) + return 1; + + rlim.rlim_cur = (rlim_t)sysconf(_SC_PAGESIZE) * 100 + HUGE_SIZE; + r = setrlimit(RLIMIT_STACK, &rlim); + if (r) { + perror("setrlimit"); + return 1; + } + + r = huge_message_send(); + if (r != -ENOMEM) + return 1; return 0; } -- 1.8.2 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel