0
votes

I have some kernel threads in Linux kernel, inside my KLM.
I have a server thread, that listens to the channel, Once it sees there is an incoming connection, it creates an accept socket, accepts the connection and spawns a child thread. It also passes the accepted socket to the child kernel thread as the (void *) argument.

The code is working fine. I had a design question.
Suppose now the threads have to be terminated, main and the child threads, what would be the best way to close the accept socket. I can see two ways,
1] The main thread waits for all the child threads to exit, each of the child threads close the accept sockets while exiting, the last child thread passes a signal to the main thread for it to exit . Here even though the main thread was the one that created the accept socket, the child threads close that socket, and they do this before the main thread exits. So is this acceptable? Any problems you guys forsee here?
2] Second is the main thread closes all the accept sockets it created before it exits. But there may be a possibility(corner case) that the main thread gets an exception and will have to close, so if it closes the accept sockets before exiting, the child threads using that socket will be in danger.

Hence i am using the first case i mentioned.Let me know what you guys think?

2
I'm curious how the children can close their sockets. Aren't they supposed to be blocked in a read operation, thus requiring the main thread to close the socket in order to unblock them? - Tudor

2 Answers

0
votes

I prefer option 1, as its a cleaner solution: as a particular thread exits, it cleans up the resources it owns (the thread does own the socket, right?). This way you wont run into any possible corner cases like you mention, where the main thread closes a socket that may possibly be in use in a child thread, etc. Using a design where a child thread owns the socket and is the only one that reads/writes/closes it is simple, clean, and leads to higher cohesion.

The second option could be implemented so as to avoid the corner cases with extra logic and signalling, but its really not necessary to add the extra complications. I always prefer to use the KISS principle.

As for your concerns about closing a socket in a different thread than where it was created: no problems here. The file descriptors (for sockets and other entities) are unique across the process. If we were talking about forked processes, well that would be different.

0
votes

first off: the "handle" to a socket is an integer, handing the integer to the close function will work regardless of context.

About your design.. I would suggest a mix of both versions.. Create a list (which you lock if accessed of course) of open sockets and have !every thread close it's socket and remove it from the main list. Upon exit of the main thread you close all remaining sockets. That way a child thread + the main thread will have to die before a socket is left open which should have the least probability of all the cases described.