On Tue, Jun 3, 2014 at 11:05 PM, Marko Rauhamaa <ma...@pacujo.net> wrote: > Chris Angelico <ros...@gmail.com>: > >> I don't see how Marko's assertion that event-driven asynchronous >> programming is a breath of fresh air compared with multithreading. The >> only way multithreading can possibly be more complicated is that >> preemption can occur anywhere - and that's exactly one of the big >> flaws in async work, if you don't do your job properly. > > Say you have a thread blocking on socket.accept(). Another thread > receives the management command to shut the server down. How do you tell > the socket.accept() thread to abort and exit? > > The classic hack is close the socket, which causes the blocking thread > to raise an exception.
How's that a hack? If you're shutting the server down, you need to close the listening socket anyway, because otherwise clients will think they can get in. Yes, I would close the socket. Or just send the process a signal like SIGINT, which will break the accept() call. (I don't know about Python specifically here; the underlying Linux API works this way, returning EINTR, as does OS/2 which is where I learned. Generally I'd have the accept() loop as the process's main loop, and spin off threads for clients.) In fact, the most likely case I'd have would be that the receipt of that signal *is* the management command to shut the server down; it might be SIGINT or SIGQUIT or SIGTERM, or maybe some other signal, but one of the easiest ways to notify a Unix process to shut down is to send it a signal. Coping with broken proprietary platforms is an exercise for the reader, but I know it's possible to terminate a console-based socket accept loop in Windows with Ctrl-C, so there ought to be an equivalent API method. > The blocking thread might be also stuck in socket.recv(). Closing the > socket from the outside is dangerous now because of race conditions. So > you will have to carefully use add locking to block an unwanted closing > of the connection. Maybe. More likely, the same situation applies - you're shutting down, so you need to close the socket anyway. I've generally found - although this may not work on all platforms - that it's perfectly safe for one thread to be blocked in recv() while another thread calls send() on the same socket, and then closes that socket. On the other hand, if your notion of shutting down does NOT include closing the socket, then you have to deal with things some other way - maybe handing the connection on to some other process, or something - so a generic approach isn't appropriate here. > But what do you do if the blocking thread is stuck in the middle of a > black box API that doesn't expose a file you could close? > > So you hope all blocking APIs have a timeout parameter. No! I never put timeouts on blocking calls to solve shutdown problems. That is a hack, and a bad one. Timeouts should be used only when the timeout is itself significant (eg if you decide that your socket connections should time out if there's no activity in X minutes, so you put a timeout on socket reads of X*60000 and close the connection cleanly if it times out). > Well, ok, > > os.kill(os.getpid(), signal.SIGKILL) > > is always an option. Yeah, that's one way. More likely, you'll find that a lesser signal also aborts the blocking API call. And even if you have to hope for an alternate API to solve this problem, how is that different from hoping that all blocking APIs have corresponding non-blocking APIs? I reiterate the example I've used a few times already: https://docs.python.org/3.4/library/logging.html#logging.Logger.debug What happens if that blocks? How can you make sure it won't? ChrisA -- https://mail.python.org/mailman/listinfo/python-list