Re: socket KPI upcall questions
Re: socket KPI upcall questions
- Subject: Re: socket KPI upcall questions
- From: Josh Graessley <email@hidden>
- Date: Mon, 27 Mar 2006 13:01:26 -0800
Answers below...
On Mar 25, 2006, at 4:16 PM, email@hidden wrote:
I'm using the socket KPI in an IOKit driver and I had some questions
about socket upcalls:
1. The documentation in kpi_socket.h for the sock_upcall function says
it can be called concurrently by multiple threads. Is this even true
for a single socket? For example, if I do a socket_connect and it
completes and calls my upcall then while my upcall is running data
becomes available on the socket, will it reenter my upcall to tell me
data is available?
In every instance that I can think of, the upcall is called on the
input thread. Since there is currently only one input thread, the
upcall will currently never be reentered. I might be forgetting
something. Either way, there are no guarantees that there will only
be one input thread in the future. The scenario you suggest above may
potentially occur in the future. You should not assume that the
upcall will not be called concurrently from multiple threads.
What I'm concerned about is that since the upcall doesn't tell you
what event it is calling you for, I'm using a state variable in my
per-socket upcall cookie to know when to move from the "connecting" to
"reading" state. If I can be re-entered while in my upcall, I'll need
to somehow protect my state variable. I've read that you can't block
in an upcall so I'd need to use something like a simple lock (is a
simple safe in an upcall?).
What you can't do in an upcall is slightly more subtle than simply
blocking. You can take a lock. It's okay if you have to block to take
that lock. What you want to be careful of is blocking on something
else that might be dependent on the input thread. For example, if you
were to block on a message you send to a user space process through a
kernel control socket, if running that process tried to read some
data from a network volume (maybe a user home directory), that
process would forever stall. Since there is only one input thread and
that's sitting waiting for the user process, the network file
operation will never complete.
2. If my socket is non-blocking, is it safe to call socket KPI
functions, such as sock_receive from my upcall? I'd like to chain
upcall completions. I see from the source in Darwin that functions
like sock_getpeername take the socket_lock so I wasn't sure if the
socket KPI is safe to call from my upcall.
Calling the socket KPI will work but it's a little messy. Most socket
functions do take the socket lock. The upcall would be mostly useless
if you couldn't make any socket calls from it, so the socket takes a
reference on the socket and drops the lock before calling the upcall
function. This means that you can make most socket calls from an
upcall function. Again, be careful because in the future, there may
be more than one input thread so you may end up with bugs. If you
read a header that has a length, then perform another read based on
that length from your upcall, it is possible that your upcall may
fire again while you were reading the length and you may try to read
the length again from another thread, screwing up your stream of data.
Calling sock_accept does not work from the upcall function.
In general, it is safer to modify shared data structures (with proper
locking) indicating the socket that has an event waiting, then wakeup
a thread you created and service the socket from that thread. You can
have one thread service many sockets. This will avoid the problems of
reentrancy in your upcall function and the limits on what you can do
to a socket from the upcall.
3. If I call socket_connect on a TCP socket, will my upcall be called
if there is a connection failure (e.g. server not listening on that
port) or only on connection success?
Yes. The upcall is called every time a wakeup on the read side
occurs. This basically means that anything that would wake a select
with that socket watching for reading will cause your upcall to fire.
The kernel has support for calling the upcall on the write side
wakeup, but that requires a flag be set and there is no way to do
that through the KPI.
4. If I call socket_connect on a TCP socket then need to abort it
before my upcall is called for connection completion, is it safe to
just call socket_close?
I believe this might work. Once socket_close returns, your upcall
will not be called again. One thing to be very careful of is not
calling socket_close while you're actually in a call to that socket
on another thread. In user space, the file descriptor does some
reference counting, so an operation on the socket in one thread will
delay a close from occurring on another thread. Since there are no
file descriptors, that reference counting is missing and the socket
will close immediately, leading to a panic.
Hope this helps.
-josh
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden