]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Flock: looped container logger
authorMaria Matejka <mq@ucw.cz>
Wed, 2 Oct 2024 20:32:46 +0000 (22:32 +0200)
committerMaria Matejka <mq@ucw.cz>
Sun, 23 Feb 2025 18:07:35 +0000 (19:07 +0100)
flock/container.c

index c582a4992b137ec2939b5a900b6b37a3bfd249a9..8634f36789c61b484101efb9c7e239b028e05de0 100644 (file)
@@ -185,6 +185,93 @@ copylink(const char *src, int sz, const char *dst)
     log(L_ERR "failed to symlink %s: %m", dst);
 }
 
+#define GETDIR(_path)  ({ char *path = _path; int fd = container_getdir(path); if (fd < 0) die("Failed to get the directory %s: %m", path); fd; })
+#define MKDIR(_path)  close(GETDIR(tmp_strdup(_path)))
+
+struct container_logger {
+  struct birdloop *loop;
+  pool *p;
+  sock *rs;
+  sock *ws;
+};
+
+static int
+container_logger_rx(sock *sk, uint _sz UNUSED)
+{
+  struct container_logger *clg = sk->data;
+  ssize_t sz = read(sk->fd, clg->ws->tpos, clg->ws->tbsize - (clg->ws->tpos - clg->ws->tbuf));
+  if (sz < 0)
+    return CALL(sk->err_hook, sk, errno), 0;
+
+  if (clg->ws->tpos == clg->ws->tbuf)
+    sk_send(clg->ws, sz);
+  else
+    clg->ws->tpos += sz;
+
+  return 1;
+}
+
+static void
+container_logger_rerr(sock *sk UNUSED, int err)
+{
+  die("Logger receiver socket closed unexpectedly: %s", strerror(err));
+}
+
+static void
+container_logger_werr(sock *sk UNUSED, int err)
+{
+  die("Logger writer closed unexpectedly: %s", strerror(err));
+}
+
+static void
+container_init_logger(void)
+{
+  struct birdloop *loop = birdloop_new(&root_pool, DOMAIN_ORDER(proto), 0, "Logger");
+  birdloop_enter(loop);
+  pool *p = rp_new(birdloop_pool(loop), birdloop_domain(loop), "Logger pool");
+  sock *s = sk_new(p);
+  s->type = SK_MAGIC;
+  s->rx_hook = container_logger_rx;
+  s->err_hook = container_logger_rerr;
+
+  unlink("/dev/log");
+  s->fd = SYSCALL(socket, AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+  union {
+    struct sockaddr sa;
+    struct sockaddr_un un;
+  } sa;
+  sa.un.sun_family = AF_UNIX;
+  strcpy(sa.un.sun_path, "/dev/log");
+  SYSCALL(bind, s->fd, &sa.sa, sizeof sa.un);
+
+  struct container_logger *clg = mb_allocz(p, sizeof *clg);
+  clg->loop = loop;
+  clg->p = p;
+  clg->rs = s;
+  s->data = clg;
+
+  if (sk_open(clg->rs, clg->loop) < 0)
+    bug("Logger failed in sk_open(r): %m");
+
+  clg->rs->type = SK_UNIX;
+
+  s = clg->ws = sk_new(p);
+  s->data = clg;
+  s->type = SK_MAGIC;
+  s->err_hook = container_logger_werr;
+  sk_set_tbsize(s, 16384);
+
+  MKDIR("/var/log");
+  s->fd = SYSCALL(open, "/var/log/syslog", O_WRONLY | O_CREAT, 0640);
+
+  if (sk_open(clg->ws, clg->loop) < 0)
+    bug("Logger failed in sk_open(w): %m");
+
+  s->type = SK_UNIX;
+
+  birdloop_leave(loop);
+}
+
 static void
 container_mainloop(int fd)
 {
@@ -202,9 +289,6 @@ container_mainloop(int fd)
       strchr(ccf.basedir, '\\'))
     die("Refusing to work with paths containing chars: ,=\\");
 
-#define GETDIR(_path)  ({ char *path = _path; int fd = container_getdir(path); if (fd < 0) die("Failed to get the directory %s: %m", path); fd; })
-#define MKDIR(_path)  close(GETDIR(lp_strdup(lp, _path)))
-
   int wfd = GETDIR(lp_sprintf(lp, "%s%s", ccf.workdir[0] == '/' ? "" : "./", ccf.workdir));
   SYSCALL(fchdir, wfd);
   close(wfd); wfd = -1;
@@ -317,49 +401,7 @@ container_mainloop(int fd)
 
   symlink("/dev/pts/ptmx", "/dev/ptmx");
 
-  pid_t logger_pid = fork();
-  if (!logger_pid)
-  {
-    /* TODO: this HAS to run as birdloop */
-    MKDIR("/var/log");
-    int wfd = SYSCALL(open, "/var/log/syslog", O_WRONLY | O_CREAT, 0640);
-
-    int fd = SYSCALL(socket, AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
-    union {
-      struct sockaddr sa;
-      struct sockaddr_un un;
-    } sa;
-    sa.un.sun_family = AF_UNIX;
-    unlink("/dev/log");
-    strcpy(sa.un.sun_path, "/dev/log");
-    SYSCALL(bind, fd, &sa.sa, sizeof sa.un);
-
-    while (true)
-    {
-      char buf[65536], *pos = buf;
-      ssize_t sz = read(fd, buf, sizeof buf);
-      if (sz < 0)
-       if (errno == EINTR)
-         continue;
-       else
-         exit(100 + errno);
-      if (sz == 0)
-       exit(0);
-
-      while (sz > 0)
-      {
-       ssize_t wz = write(wfd, pos, sz);
-       if (wz < 0)
-         if (errno == EINTR)
-           continue;
-         else
-           exit(200 + errno);
-       ASSERT_DIE(wz > 0);
-       sz -= wz;
-       pos += wz;
-      }
-    }
-  }
+  container_init_logger();
 
   while (1)
   {