kdbus.h: add KDBUS_ITEM_SIGMASK (ABI break)
authorDaniel Mack <daniel@zonque.org>
Wed, 17 Dec 2014 22:20:21 +0000 (23:20 +0100)
committerDaniel Mack <daniel@zonque.org>
Wed, 17 Dec 2014 22:28:49 +0000 (23:28 +0100)
Introduce KDBUS_ITEM_SIGMASK to store a 64-bit signal mask.

If attached to KDBUS_CMD_SEND in sync mode, the provided signal mask
will be set before the kernel blocks the execution, and restored
afterwards, unless the syscall is interrupted. This makes the
KDBUS_CMD_SEND ioctl behavior similar to what ppoll() does.

Signed-off-by: Daniel Mack <daniel@zonque.org>
connection.c
item.c
kdbus.h

index fc60dec3e55c7891c3da0a9dec3dd3375158a374..28973dc07390c976b3765045dd6dd4b6b4b782d9 100644 (file)
@@ -621,6 +621,8 @@ static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src,
                                 u64 timeout_ns)
 {
        struct kdbus_queue_entry *entry;
+       struct kdbus_item *sigmask_item;
+       sigset_t sigsaved;
        int r, ret;
 
        if (WARN_ON(!reply_wait))
@@ -631,6 +633,16 @@ static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src,
         * by the timeout scans that might be conducted for other,
         * asynchronous replies of conn_src.
         */
+
+       sigmask_item = kdbus_items_get(cmd_send->items,
+                                      KDBUS_ITEMS_SIZE(cmd_send, items),
+                                      KDBUS_ITEM_SIGMASK);
+       if (sigmask_item) {
+               sigset_t sigmask;
+               memcpy(&sigmask, &sigmask_item->sigmask, sizeof(sigmask));
+               sigprocmask(SIG_SETMASK, &sigmask, &sigsaved);
+       }
+
        r = wait_event_interruptible_timeout(reply_wait->reply_dst->wait,
                !reply_wait->waiting || !kdbus_conn_active(conn_src),
                nsecs_to_jiffies(timeout_ns));
@@ -650,6 +662,9 @@ static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src,
                return r;
        }
 
+       if (sigmask_item)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
        if (r == 0)
                ret = -ETIMEDOUT;
        else if (!kdbus_conn_active(conn_src))
diff --git a/item.c b/item.c
index c480fa38a280f5c5537576a359129e691a2a9012..d813823c86edbcddd2985663bd8e5b82f1f11475 100644 (file)
--- a/item.c
+++ b/item.c
@@ -13,6 +13,7 @@
 
 #include <linux/ctype.h>
 #include <linux/fs.h>
+#include <linux/signal.h>
 #include <linux/string.h>
 
 #include "item.h"
@@ -131,6 +132,11 @@ static int kdbus_item_validate(const struct kdbus_item *item)
                        return -EINVAL;
                break;
 
+       case KDBUS_ITEM_SIGMASK:
+               if (payload_size != sizeof(sigset_t))
+                       return -EINVAL;
+               break;
+
        case KDBUS_ITEM_NAME:
        case KDBUS_ITEM_DST_NAME:
        case KDBUS_ITEM_PID_COMM:
diff --git a/kdbus.h b/kdbus.h
index 88e8259095bf9cf5c3a9d109ac80e3d8ca02bc9c..4119969b442ec37cb3d9849ca7007cf683d6435f 100644 (file)
--- a/kdbus.h
+++ b/kdbus.h
@@ -301,6 +301,7 @@ enum kdbus_item_type {
        KDBUS_ITEM_ATTACH_FLAGS_RECV,
        KDBUS_ITEM_ID,
        KDBUS_ITEM_NAME,
+       KDBUS_ITEM_SIGMASK,
 
        /* keep these item types in sync with KDBUS_ATTACH_* flags */
        _KDBUS_ITEM_ATTACH_BASE = 0x1000,
@@ -380,6 +381,7 @@ struct kdbus_item {
                struct kdbus_notify_name_change name_change;
                struct kdbus_notify_id_change id_change;
                struct kdbus_policy_access policy_access;
+               __u64 sigmask;
        };
 };