Add RWF_NOSIGNAL flag for pwritev2
For a user mode library to avoid generating SIGPIPE signals (e.g. because this behaviour is not portable across operating systems) is cumbersome. It is generally bad form to change the process-wide signal mask in a library, so a local solution is needed instead. For I/O performed directly using system calls (synchronous or readiness based asynchronous) this currently involves applying a thread-specific signal mask before the operation and reverting it afterwards. This can be avoided when it is known that the file descriptor refers to neither a pipe nor a socket, but a conservative implementation must always apply the mask. This incurs the cost of two additional system calls. In the case of sockets, the existing MSG_NOSIGNAL flag can be used with send. For asynchronous I/O performed using io_uring, currently the only option (apart from MSG_NOSIGNAL for sockets), is to mask SIGPIPE entirely in the call to io_uring_enter. Thankfully io_uring_enter takes a signal mask, so only a single syscall is needed. However, copying the signal mask on every call incurs a non-zero performance penalty. Furthermore, this mask applies to all completions, meaning that if the non-signaling behaviour is desired only for some subset of operations, the desired signals must be raised manually from user-mode depending on the completed operation. Add RWF_NOSIGNAL flag for pwritev2. This flag prevents the SIGPIPE signal from being raised when writing on disconnected pipes or sockets. The flag is handled directly by the pipe filesystem and converted to the existing MSG_NOSIGNAL flag for sockets. Signed-off-by: Lauri Vasama <git@vasama.org> Link: https://lore.kernel.org/20250827133901.1820771-1-git@vasama.org Reviewed-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
38d1227fa7
commit
db2ab24a34
|
@ -458,7 +458,8 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
|
|||
mutex_lock(&pipe->mutex);
|
||||
|
||||
if (!pipe->readers) {
|
||||
send_sig(SIGPIPE, current, 0);
|
||||
if ((iocb->ki_flags & IOCB_NOSIGNAL) == 0)
|
||||
send_sig(SIGPIPE, current, 0);
|
||||
ret = -EPIPE;
|
||||
goto out;
|
||||
}
|
||||
|
@ -498,7 +499,8 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
|
|||
|
||||
for (;;) {
|
||||
if (!pipe->readers) {
|
||||
send_sig(SIGPIPE, current, 0);
|
||||
if ((iocb->ki_flags & IOCB_NOSIGNAL) == 0)
|
||||
send_sig(SIGPIPE, current, 0);
|
||||
if (!ret)
|
||||
ret = -EPIPE;
|
||||
break;
|
||||
|
|
|
@ -356,6 +356,7 @@ struct readahead_control;
|
|||
#define IOCB_APPEND (__force int) RWF_APPEND
|
||||
#define IOCB_ATOMIC (__force int) RWF_ATOMIC
|
||||
#define IOCB_DONTCACHE (__force int) RWF_DONTCACHE
|
||||
#define IOCB_NOSIGNAL (__force int) RWF_NOSIGNAL
|
||||
|
||||
/* non-RWF related bits - start at 16 */
|
||||
#define IOCB_EVENTFD (1 << 16)
|
||||
|
|
|
@ -430,10 +430,13 @@ typedef int __bitwise __kernel_rwf_t;
|
|||
/* buffered IO that drops the cache after reading or writing data */
|
||||
#define RWF_DONTCACHE ((__force __kernel_rwf_t)0x00000080)
|
||||
|
||||
/* prevent pipe and socket writes from raising SIGPIPE */
|
||||
#define RWF_NOSIGNAL ((__force __kernel_rwf_t)0x00000100)
|
||||
|
||||
/* mask of flags supported by the kernel */
|
||||
#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\
|
||||
RWF_APPEND | RWF_NOAPPEND | RWF_ATOMIC |\
|
||||
RWF_DONTCACHE)
|
||||
RWF_DONTCACHE | RWF_NOSIGNAL)
|
||||
|
||||
#define PROCFS_IOCTL_MAGIC 'f'
|
||||
|
||||
|
|
|
@ -1176,6 +1176,9 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
|||
if (sock->type == SOCK_SEQPACKET)
|
||||
msg.msg_flags |= MSG_EOR;
|
||||
|
||||
if (iocb->ki_flags & IOCB_NOSIGNAL)
|
||||
msg.msg_flags |= MSG_NOSIGNAL;
|
||||
|
||||
res = __sock_sendmsg(sock, &msg);
|
||||
*from = msg.msg_iter;
|
||||
return res;
|
||||
|
|
Loading…
Reference in New Issue