fsync() on unix domain sockets?
Let's say someone had written a win32 emulator that ran in userspace, and was using unix domain sockets to emulate win32 named pipes. (Yes, this is how Wine does it at the moment, but it's a poor fit, and they're thinking of switching to emulating them 100% in userspace so they can get the semantics right.)
It turns out that in this situation, it would be handy
for fsync() to work on unix domain sockets. This would
require a bit of plumbing to let sockets expose an fsync() method, together with an fsync() method for unix domain sockets.
After thinking about this a bit, I couldn't resist
writing that method for stream sockets. Being a kernel newbie,
I am unsure if I got the locking and reference counting right.
Anyone care to peek at it and see if there are glaring problems?
(If not, I guess I could go do the needed plumbing and see how it works in practice.)
Thanks,
Dan
/* to be added to net/unix/af_unix.c */
static long unix_stream_fsync(unix_socket * sk)
{
int err;
long timeo;
unix_socket *other;
DECLARE_WAITQUEUE(wait, current);
timeo = sock_sndtimeo(sk, 0);
err = -ENOTCONN;
other = unix_peer_get(sk);
if (!other)
goto out;
unix_state_rlock(sk);
add_wait_queue(sk->sleep, &wait);
unix_state_runlock(sk);
for (;;) {
int breakme;
unix_state_rlock(other);
breakme = !skb_queue_len(&other->receive_queue) ||
other->err ||
(other->shutdown & RCV_SHUTDOWN) ||
!timeo;
unix_state_runlock(other);
if (breakme)
break;
if (signal_pending(current))
goto out_sig;
set_current_state(TASK_INTERRUPTIBLE);
timeo = schedule_timeout(timeo);
}
err = 0;
out_run:
__set_current_state(TASK_RUNNING);
unix_state_rlock(sk);
remove_wait_queue(sk->sleep, &wait);
unix_state_runlock(sk);
sock_put(other);out:
return err;
out_sig:
err = sock_intr_errno(timeo);
goto out_run;
}Signature · 3 lines
Dan Kegel http://www.kegel.com http://counter.li.org/cgi-bin/runscript/display-person.cgi?user=78045
Quoted 7 lines · Dan Kegel
Let's say someone had written a win32 emulator that ran in userspace, and was using unix domain sockets to emulate win32 named pipes. (Yes, this is how Wine does it at the moment, but it's a poor fit, and they're thinking of switching to emulating them 100% in userspace so they can get the semantics right.)
[SNIPPED...]
What problem are you attempting to fix? You will never find any unflushed buffers in Unix Domain sockets because you need an active reader before the write will succeed. The writer will block until the reader has all the data. That's why they are used for synchronization. Of course you don't know that the reader has actually used the data, that's why you use semiphores or other synchronizing elements. Unlike network sockets, where the kernel just promises it will eventually get the data to a connected socket, Unix domain sockets don't return control to the writer until the reader has read the data.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips). Why is the government concerned about the lunatic fringe? Think about it.
Quoted 4 lines · Richard B. Johnson
You will never find
any unflushed buffers in Unix Domain sockets because you need an active reader before the write will succeed. The writer will block until the reader has all the data.
OK, then, at least I had a nice read through the af_unix.c code. I guess I'll write a little test program to verify the problem I thought I had doesn't exist.
Thanks,
Dan
Signature · 3 lines
Dan Kegel http://www.kegel.com http://counter.li.org/cgi-bin/runscript/display-person.cgi?user=78045