]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sink: add a support for file descriptors
authorWilly Tarreau <w@1wt.eu>
Tue, 20 Aug 2019 09:57:52 +0000 (11:57 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 22 Aug 2019 18:21:00 +0000 (20:21 +0200)
This is the most basic type of sink. It pre-registers "stdout" and
"stderr", and is able to use writev() on them. The writev() operation
is locked to avoid mixing outputs. It's likely that the registration
should move somewhere else to take into account the fact that stdout
and stderr are still opened or are closed.

include/proto/sink.h
include/types/sink.h
src/sink.c

index ae493d4ce1819d4a62762392d9a9e8a5dcc63c5a..0d8dd7dfc59f51b782cb48dcf428fbf3756271e4 100644 (file)
@@ -28,6 +28,7 @@
 extern struct list sink_list;
 
 struct sink *sink_find(const char *name);
+struct sink *sink_new_fd(const char *name, const char *desc, enum sink_fmt fmt, int fd);
 void sink_write(struct sink *sink, const struct ist msg[], size_t nmsg);
 
 #endif /* _PROTO_SINK_H */
index 35333144dece29e856ab47b838df324e2ec8cf77..32c056712fead517bdd716014407f439a1a3e5d1 100644 (file)
 #include <common/ist.h>
 
 /* A sink may be of several types. For now the following types are supported:
- * (none yet)
+ *   - file descriptor (such as stdout)
  */
 enum sink_type {
        SINK_TYPE_NEW,      // not yet initialized
+       SINK_TYPE_FD,       // events sent to a file descriptor
 };
 
 /* This indicates the default event format, which is the destination's
@@ -59,6 +60,7 @@ struct sink {
        struct {
                unsigned int dropped; // dropped events since last one.
                __decl_hathreads(HA_RWLOCK_T lock); // used by some types
+               int fd;               // fd num for FD type sink
        } ctx;
 };
 
index 6cebf2aa5106dbab514ee5f1839a062d0715b51d..f3e18ccb20c09bf0d49d84a8c6ef07a9e917950a 100644 (file)
@@ -43,7 +43,7 @@ struct sink *sink_find(const char *name)
  * exists with the same name, it will be returned. The caller can detect it as
  * a newly created one has type SINK_TYPE_NEW.
  */
-static __maybe_unused struct sink *__sink_new(const char *name, const char *desc, enum sink_fmt fmt)
+static struct sink *__sink_new(const char *name, const char *desc, enum sink_fmt fmt)
 {
        struct sink *sink;
 
@@ -64,6 +64,7 @@ static __maybe_unused struct sink *__sink_new(const char *name, const char *desc
        sink->syslog_minlvl   = 0;
        sink->maxlen = MAX_SYSLOG_LEN;
        /* address will be filled by the caller if needed */
+       sink->ctx.fd = -1;
        sink->ctx.dropped = 0;
        HA_RWLOCK_INIT(&sink->ctx.lock);
        LIST_ADDQ(&sink_list, &sink->sink_list);
@@ -71,6 +72,29 @@ static __maybe_unused struct sink *__sink_new(const char *name, const char *desc
        return sink;
 }
 
+/* creates a sink called <name> of type FD associated to fd <fd>, format <fmt>,
+ * and description <desc>. Returns NULL on allocation failure or conflict.
+ * Perfect duplicates are merged (same type, fd, and name).
+ */
+struct sink *sink_new_fd(const char *name, const char *desc, enum sink_fmt fmt, int fd)
+{
+       struct sink *sink;
+
+       sink = __sink_new(name, desc, fmt);
+       if (!sink || (sink->type == SINK_TYPE_FD && sink->ctx.fd == fd))
+               goto end;
+
+       if (sink->type != SINK_TYPE_NEW) {
+               sink = NULL;
+               goto end;
+       }
+
+       sink->type = SINK_TYPE_FD;
+       sink->ctx.fd = fd;
+ end:
+       return sink;
+}
+
 /* tries to send <nmsg> message parts (up to 8, ignored above) from message
  * array <msg> to sink <sink>. Formating according to the sink's preference is
  * done here. Lost messages are accounted for in the sink's counter.
@@ -109,13 +133,31 @@ void sink_write(struct sink *sink, const struct ist msg[], size_t nmsg)
                msg++; nmsg--;
        }
 
-       /* now deal with the various sink types here */
+       if (sink->type == SINK_TYPE_FD) {
+               /* For the FD we always emit the trailing \n. It was already provisioned above. */
+               iovec[vec].iov_base = "\n";
+               iovec[vec].iov_len  = 1;
+               vec++;
+
+               HA_RWLOCK_WRLOCK(LOGSRV_LOCK, &sink->ctx.lock);
+               sent = writev(sink->ctx.fd, iovec, vec);
+               HA_RWLOCK_WRUNLOCK(LOGSRV_LOCK, &sink->ctx.lock);
+               /* sent > 0 if the message was delivered */
+       }
 
        /* account for errors now */
        if (sent <= 0)
                HA_ATOMIC_ADD(&sink->ctx.dropped, 1);
 }
 
+static void sink_init()
+{
+       sink_new_fd("stdout", "standard output (fd#1)", SINK_FMT_RAW, 1);
+       sink_new_fd("stderr", "standard output (fd#2)", SINK_FMT_RAW, 2);
+}
+
+INITCALL0(STG_REGISTER, sink_init);
+
 /*
  * Local variables:
  *  c-indent-level: 8