Duncan C
Duncan C

Reputation: 131408

Can you kill a process on a conncurrent dispatch queue

I'm adapting Linux networking code to also run on iOS. It uses POSIX listen() and accept() calls to listen for and open socket connections.

I have dispatch queues that listen for and accept new connections, and then other queues that manage open connections.

The jobs running on all the queues have run loops that terminate when a global quit flag is set to true.

The listen and accept calls are blocking calls, and if I need to shut down the app, the queues running those calls will sometimes stall for a minute or two, blocked. (Usually in the accept call.)

Is there a way to terminate the processes that are blocked? There are discussion threads (not POSIX threads) like this one here on SO that say that there is not a way built into GCD. I guess I could figure out which thread is currently blocked and use POSIX calls to kill that thread, but that might cause problems with GCD (I don't know how GCD would handle it if one or more of its worker threads was terminated.)

Has anybody attempted that approach?

Upvotes: 1

Views: 1235

Answers (1)

Rob Napier
Rob Napier

Reputation: 299305

You definitely should not try to kill a GCD thread. They don't belong to you; they belong to GCD.

The best way to cancel an accept in a multi-threaded application during shutdown is to close the socket. This is particularly useful during shutdown because there are no race-conditions around socket reuse (if the file descriptor might be reused, you have to make sure you're closing the right socket).

If it is impossible to close the socket, you can send a signal to the thread with pthread_kill and an empty signal handler to cause the accept to fail with EINTR. But then you shouldn't use GCD for this. GCD actually blocks all maskable signals so it won't work, but if it did, it would be a bad idea. GCD threads are part of a pool and are reused.

All that said, if at all possible, I'd really recommend converting this code to use CFStream rather than directly calling accept. It's going to integrate with the system much better. For an excellent example of integrating raw sockets, CFStream and GCD, see Robbie Hanson's CocoaAsyncSocket. While this is in ObjC, CFStream is a Core Foundation object and can be managed entirely in C. You may find that CocoaAsyncSocket can replace all your code, however.

Upvotes: 3

Related Questions