summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2005-03-07 07:26:42 +0000
committersobomax <sobomax@FreeBSD.org>2005-03-07 07:26:42 +0000
commita5d845fec654f4b43610ba376ae17fa9309853b0 (patch)
tree0b22e0cd71756d80eb0006639568691eaa0e3623
parent7d3d18d907337f6f78e665a6e87ad183892db3c8 (diff)
downloadFreeBSD-src-a5d845fec654f4b43610ba376ae17fa9309853b0.zip
FreeBSD-src-a5d845fec654f4b43610ba376ae17fa9309853b0.tar.gz
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 <killing@multiplay.co.uk> MFC after: 3 days
-rw-r--r--sys/compat/linux/linux_socket.c27
1 files changed, 25 insertions, 2 deletions
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 {
OpenPOWER on IntegriCloud