From a5d845fec654f4b43610ba376ae17fa9309853b0 Mon Sep 17 00:00:00 2001 From: sobomax Date: Mon, 7 Mar 2005 07:26:42 +0000 Subject: Handle MSG_NOSIGNAL flag in linux_send() by setting SO_NOSIGPIPE on socket for the duration of the send() call. Such approach may be less than ideal in threading environment, when several threads share the same socket and it might happen that several of them are calling linux_send() at the same time with and without SO_NOSIGPIPE set. However, such race condition is very unlikely in practice, therefore this change provides practical improvement compared to the previous behaviour. PR: kern/76426 Submitted by: Steven Hartland MFC after: 3 days --- sys/compat/linux/linux_socket.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'sys/compat/linux/linux_socket.c') diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index dd358ce..6f6f501 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -816,18 +816,41 @@ linux_send(struct thread *td, struct linux_send_args *args) caddr_t to; int tolen; } */ bsd_args; - int error; + int error, nosigpipe, onosigpipe; + socklen_t valsize; if ((error = copyin(args, &linux_args, sizeof(linux_args)))) return (error); + if (linux_args.flags & LINUX_MSG_NOSIGNAL) { + valsize = sizeof(onosigpipe); + error = kern_getsockopt(td, linux_args.s, SOL_SOCKET, + SO_NOSIGPIPE, &onosigpipe, UIO_SYSSPACE, + &valsize); + if (error != 0) + return error; + if (onosigpipe == 0) { + nosigpipe = 1; + error = kern_setsockopt(td, linux_args.s, SOL_SOCKET, + SO_NOSIGPIPE, &nosigpipe, UIO_SYSSPACE, + sizeof(nosigpipe)); + if (error != 0) + return error; + } + } bsd_args.s = linux_args.s; bsd_args.buf = (caddr_t)PTRIN(linux_args.msg); bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; bsd_args.to = NULL; bsd_args.tolen = 0; - return (sendto(td, &bsd_args)); + error = sendto(td, &bsd_args); + if ((linux_args.flags & LINUX_MSG_NOSIGNAL) && (onosigpipe == 0)) { + kern_setsockopt(td, linux_args.s, SOL_SOCKET, + SO_NOSIGPIPE, &onosigpipe, UIO_SYSSPACE, + sizeof(onosigpipe)); + } + return error; } struct linux_recv_args { -- cgit v1.1