]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: print the masks specified in signalfds
authorMasatake YAMATO <yamato@redhat.com>
Tue, 6 Jun 2023 22:30:06 +0000 (07:30 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Wed, 7 Jun 2023 22:35:20 +0000 (07:35 +0900)
An example output:

    # ./lsfd -p "$(pidof systemd-journald)" -Q '(TYPE == "signalfd")'

    COMMAND             PID USER ASSOC MODE     TYPE       SOURCE MNTID INODE NAME
    systemd-journal 2382709 root   238  rw- signalfd anon_inodefs    15  1060 mask=USR1,USR2
    systemd-journal 2382709 root   239  rw- signalfd anon_inodefs    15  1060 mask=INT,TERM
    systemd-journal 2382709 root   240  rw- signalfd anon_inodefs    15  1060 mask=35

Using signum_to_signame is suggested by Karel Zak <kzak@redhat.com>.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
misc-utils/lsfd-unkn.c
misc-utils/lsfd.c
misc-utils/lsfd.h

index 9af0816f11697634c134e1d9be65424be128a992..d5e44aa9a2b020caad58ca527b5706da7c778dc6 100644 (file)
@@ -22,6 +22,7 @@
 #include "xalloc.h"
 #include "nls.h"
 #include "libsmartcols.h"
+#include "signames.h"
 
 #include "lsfd.h"
 
@@ -715,6 +716,103 @@ static const struct anon_ops anon_timerfd_ops = {
        .handle_fdinfo = anon_timerfd_handle_fdinfo,
 };
 
+/*
+ * signalfd
+ */
+struct anon_signalfd_data {
+       uint64_t sigmask;
+};
+
+static bool anon_signalfd_probe(const char *str)
+{
+       return strncmp(str, "[signalfd]", 10) == 0;
+}
+
+static void anon_signalfd_init(struct unkn *unkn)
+{
+       unkn->anon_data = xcalloc(1, sizeof(struct anon_signalfd_data));
+}
+
+static void anon_signalfd_free(struct unkn *unkn)
+{
+       struct anon_signalfd_data *data = unkn->anon_data;
+       free(data);
+}
+
+static int anon_signalfd_handle_fdinfo(struct unkn *unkn, const char *key, const char *value)
+{
+       struct anon_signalfd_data *data = (struct anon_signalfd_data *)unkn->anon_data;
+
+       if (strcmp(key, "sigmask") == 0) {
+               if (ul_strtou64(value, &data->sigmask, 16) < 0) {
+                       data->sigmask = 0;
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+static char *anon_signalfd_make_mask_string(const char* prefix, uint64_t sigmask)
+{
+       char *str = NULL;
+
+       for (size_t i = 0; i < sizeof(sigmask) * 8; i++) {
+               if ((((uint64_t)0x1) << i) & sigmask) {
+                       const int signum = i + 1;
+                       const char *signame = signum_to_signame(signum);
+
+                       if (str)
+                               xstrappend(&str, ",");
+                       else if (prefix)
+                               xstrappend(&str, prefix);
+
+                       if (signame) {
+                               xstrappend(&str, signame);
+                       } else {
+                               char buf[BUFSIZ];
+                               snprintf(buf, sizeof(buf), "%d", signum);
+                               xstrappend(&str, buf);
+                       }
+               }
+       }
+
+       return str;
+}
+
+static char *anon_signalfd_get_name(struct unkn *unkn)
+{
+       struct anon_signalfd_data *data = (struct anon_signalfd_data *)unkn->anon_data;
+       return anon_signalfd_make_mask_string("mask=", data->sigmask);
+}
+
+static bool anon_signalfd_fill_column(struct proc *proc  __attribute__((__unused__)),
+                                     struct unkn *unkn,
+                                     struct libscols_line *ln __attribute__((__unused__)),
+                                     int column_id,
+                                     size_t column_index __attribute__((__unused__)),
+                                     char **str)
+{
+       struct anon_signalfd_data *data = (struct anon_signalfd_data *)unkn->anon_data;
+
+       switch(column_id) {
+       case COL_SIGNALFD_MASK:
+               *str = anon_signalfd_make_mask_string(NULL, data->sigmask);
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct anon_ops anon_signalfd_ops = {
+       .class = "signalfd",
+       .probe = anon_signalfd_probe,
+       .get_name = anon_signalfd_get_name,
+       .fill_column = anon_signalfd_fill_column,
+       .init = anon_signalfd_init,
+       .free = anon_signalfd_free,
+       .handle_fdinfo = anon_signalfd_handle_fdinfo,
+};
+
 /*
  * generic (fallback implementation)
  */
@@ -732,6 +830,7 @@ static const struct anon_ops *anon_ops[] = {
        &anon_eventfd_ops,
        &anon_eventpoll_ops,
        &anon_timerfd_ops,
+       &anon_signalfd_ops,
 };
 
 static const struct anon_ops *anon_probe(const char *str)
index decce120e45d7a7f77b80636db14a510128731bd..590787bf43f06ce0d764d98f187077cb04e32db1 100644 (file)
@@ -255,6 +255,9 @@ static const struct colinfo infos[] = {
        [COL_RDEV]             = { "RDEV",
                                   0,   SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
                                   N_("device ID (if special file)") },
+       [COL_SIGNALFD_MASK]    = { "SIGNALFD.MASK",
+                                  0,   SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
+                                  N_("masked signals") },
        [COL_SIZE]             = { "SIZE",
                                   4,   SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER,
                                   N_("file size"), },
index 7dcb553bf1737dd97e055358289196d701cc0ba5..aeda9ef85774dd5c31d69d97c04fab66b7d50f0a 100644 (file)
@@ -82,6 +82,7 @@ enum {
        COL_POS,
        COL_RAW_PROTOCOL,
        COL_RDEV,
+       COL_SIGNALFD_MASK,
        COL_SIZE,
        COL_SOCK_LISTENING,
        COL_SOCK_NETNS,