service: if logging start app with LD_PRELOAD & lib for line buffering
authorRafał Miłecki <zajec5@gmail.com>
Mon, 6 Jul 2015 21:37:11 +0000 (23:37 +0200)
committerSteven Barth <steven@midlink.org>
Tue, 7 Jul 2015 08:36:04 +0000 (10:36 +0200)
Using pipe automatically switches service to block buffering which kind
of breaks our logging. We won't get anything from stdout FD until the
buffer gets filled fully or the service exits. This makes log messages
appear with an unwanted delay.
This change adds a tiny libsetlbf.so switching stdout to line buffering
and uses this lib for every logging-enabled service started by procd.
We don't need any extra change for stderr as it's unbuffered by default.

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Modified to use no buffering to align with stderr. Several cleanups.

Signed-off-by: Steven Barth <steven@midlink.org>
CMakeLists.txt
service/instance.c
service/setlbf.c [new file with mode: 0644]

index dfa94139eb9ddb159845aadb7d3a7303f2d02368..6af17a3a1decd587e7da4c9459686c2a0eed983a 100644 (file)
@@ -10,6 +10,13 @@ IF(APPLE)
   LINK_DIRECTORIES(/opt/local/lib)
 ENDIF()
 
+
+ADD_LIBRARY(setlbf SHARED service/setlbf.c)
+INSTALL(TARGETS setlbf
+       LIBRARY DESTINATION lib
+)
+
+
 SET(SOURCES procd.c signal.c watchdog.c state.c        inittab.c rcS.c ubus.c system.c
        service/service.c service/instance.c service/validate.c service/trigger.c service/watch.c
        plug/coldplug.c plug/hotplug.c utils/utils.c)
index 35b2deffe80a576fd0d21a83df9d9f18e0fc524e..40ff021fcc1ce48fbed24fdab718cf88436fbed3 100644 (file)
@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  */
 
+#define _GNU_SOURCE
 #include <sys/resource.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -19,6 +20,7 @@
 #include <net/if.h>
 #include <unistd.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <fcntl.h>
 #include <pwd.h>
 #include <libgen.h>
@@ -224,8 +226,11 @@ instance_run(struct service_instance *in, int _stdout, int _stderr)
        struct blobmsg_list_node *var;
        struct blob_attr *cur;
        char **argv;
+       char *ld_preload;
        int argc = 1; /* NULL terminated */
        int rem, _stdin;
+       bool seccomp = !in->trace && !in->has_jail && in->seccomp;
+       bool setlbf = _stdout >= 0;
 
        if (in->nice)
                setpriority(PRIO_PROCESS, 0, in->nice);
@@ -236,10 +241,14 @@ instance_run(struct service_instance *in, int _stdout, int _stderr)
        blobmsg_list_for_each(&in->env, var)
                setenv(blobmsg_name(var->data), blobmsg_data(var->data), 1);
 
-       if (!in->trace && !in->has_jail && in->seccomp) {
+       if (seccomp)
                setenv("SECCOMP_FILE", in->seccomp, 1);
-               setenv("LD_PRELOAD", "/lib/libpreload-seccomp.so", 1);
-       }
+
+       if ((seccomp || setlbf) && asprintf(&ld_preload, "LD_PRELOAD=%s%s%s",
+                       seccomp ? "/lib/libpreload-seccomp.so" : "",
+                       seccomp && setlbf ? ":" : "",
+                       setlbf ? "/lib/libsetlbf.so" : "") > 0)
+               putenv(ld_preload);
 
        blobmsg_list_for_each(&in->limits, var)
                instance_limits(blobmsg_name(var->data), blobmsg_data(var->data));
diff --git a/service/setlbf.c b/service/setlbf.c
new file mode 100644 (file)
index 0000000..94c251e
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+static void __attribute__((constructor)) setlbf(void)
+{
+       setbuf(stdout, NULL);
+}