Path: csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail From: Israel Brewster Newsgroups: comp.lang.python Subject: Bi-directional sub-process communication Date: Mon, 23 Nov 2015 08:54:38 -0900 Lines: 91 Message-ID: Mime-Version: 1.0 (Mac OS X Mail 9.1 \(3096.5\)) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable X-Trace: news.uni-berlin.de eQsqJtQyxb8hvYKScY+huApWrTmo87m+fAtlhKhcQptQ== Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.004 X-Spam-Evidence: '*H*': 0.99; '*S*': 0.00; 'elif': 0.04; 'one?': 0.05; 'testing,': 0.05; 'tries': 0.05; 'default.': 0.07; 'responding': 0.07; 'subject:skip:c 10': 0.07; 'any)': 0.09; 'concern:': 0.09; 'subject:process': 0.09; 'timeout': 0.09; 'thread': 0.10; 'python': 0.10; 'causing': 0.13; 'helvetica;': 0.15; 'server,': 0.15; '(cherrypy': 0.16; 'break-word;': 0.16; 'it.i': 0.16; 'order?': 0.16; 'provided!': 0.16; 'reads,': 0.16; 'received:io': 0.16; 'received:psf.io': 0.16; 'seconds.': 0.16; 'space;': 0.16; 'subject:sub': 0.16; 'threads': 0.16; 'timeout.': 0.16; 'webapp': 0.16; 'which,': 0.16; 'word-wrap:': 0.16; 'app': 0.16; 'say,': 0.18; 'try:': 0.18; 'runs': 0.18; 'all,': 0.20; 'prevent': 0.20; 'problem:': 0.22; 'trying': 0.22; '(or': 0.23; 'seems': 0.23; 'requests': 0.25; 'skip:- 40': 0.25; "i've": 0.25; "doesn't": 0.26; 'handling': 0.27; 'order.': 0.27; 'possibility': 0.27; '12px;': 0.27; 'tech': 0.27; "skip:' 10": 0.28; 'skip:u 20': 0.28; 'actual': 0.28; 'fine': 0.28; '(maybe': 0.29; 'concern': 0.29; 'flying': 0.29; 'gil': 0.29; 'locks': 0.29; 'occasionally': 0.29; 'queue': 0.29; 'secondly': 0.29; 'code:': 0.29; 'typically': 0.29; 'posts': 0.30; 'to:name:python-list': 0.30; 'seconds': 0.31; 'post': 0.31; 'another': 0.32; "can't": 0.32; 'implement': 0.32; 'posting': 0.32; 'getting': 0.33; 'run': 0.33; 'class': 0.33; 'problem': 0.33; 'lock': 0.33; 'skip:- 10': 0.34; '0);': 0.34; 'except': 0.34; 'worked': 0.34; 'running': 0.34; 'that,': 0.34; 'so,': 0.35; 'skip:c 30': 0.35; 'next': 0.35; 'could': 0.35; 'instance': 0.35; 'quite': 0.35; 'something': 0.35; 'item': 0.35; 'sometimes': 0.35; 'but': 0.36; 'should': 0.36; 'there': 0.36; 'possible': 0.36; 'child': 0.36; 'to:addr:python-list': 0.36; 'received:10': 0.37; 'thanks': 0.37; 'charset:us-ascii': 0.37; 'end': 0.39; 'skip:- 20': 0.39; 'enough': 0.39; 'subject:-': 0.39; 'to:addr:python.org': 0.40; 'where': 0.40; 'hang': 0.60; 'waiting': 0.60; 'care': 0.60; 'avoid': 0.61; 'header:Message- Id:1': 0.61; 'side': 0.62; 'more': 0.63; 'different': 0.63; 'complete': 0.63; 'information': 0.63; 'times': 0.63; 'believe': 0.66; 'real-world': 0.66; 'received:10.9': 0.66; 'potentially': 0.67; 'situation': 0.67; 'guaranteed': 0.67; 'production': 0.67; 'therefore': 0.67; 'risk': 0.68; 'increase': 0.73; 'gotten': 0.76; 'received:12': 0.81; 'launches': 0.84; 'received,': 0.84; 'simple:': 0.84; 'skip:4 60': 0.84; '0px;">': 0.91; 'alaska': 0.91; 'preventing': 0.91; 'start;': 0.91; 'try.': 0.91; 'responses': 0.93; 'tied': 0.93 X-Warning: RFC compliance checks disabled due to whitelist X-Warning: Reverse-Path DNS check skipped due to whitelist X-Warning: Maximum message size check skipped due to whitelist X-Warning: Realtime Block Lists skipped due to whitelist X-Warning: System filters skipped due to whitelist X-Warning: Domain filters skipped due to whitelist X-Warning: User filters skipped due to whitelist X-Warning: Anti-Spam check skipped due to whitelist X-Whitelist: 2147483645 X-Envelope-From: israel@ravnalaska.net X-Envelope-To: python-list@python.org X-Mailer: Apple Mail (2.3096.5) X-Content-Filtered-By: Mailman/MimeDel 2.1.20+ X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Xref: csiph.com comp.lang.python:99279 I have a multi-threaded python app (CherryPy WebApp to be exact) that = launches a child process that it then needs to communicate with = bi-driectionally. To implement this, I have used a pair of Queues: a = child_queue which I use for master->child communication, and a = master_queue which is used for child->master communication. The way I have the system set up, the child queue runs a loop in a tread = that waits for messages on child_queue, and when received responds = appropriately depending on the message received, which sometimes = involves posting a message to master_queue. On the master side, when it needs to communicate with the child process, = it posts a message to child_queue, and if the request requires a = response it will then immediately start waiting for a message on = master_queue, typically with a timeout. While this process works well in testing, I do have one concern (maybe = unfounded) and a real-world issue Concern: Since the master process is multi-threaded, it seems likely = enough that multiple threads on the master side would make requests at = the same time. I understand that the Queue class has locks that make = this fine (one thread will complete posting the message before the next = is allowed to start), and since the child process only has a single = thread processing messages from the queue, it should process them in = order and post the responses (if any) to the master_queue in order. But = now I have multiple master processes all trying to read master_queue at = the same time. Again, the locks will take care of this and prevent any = overlapping reads, but am I guaranteed that the threads will obtain the = lock and therefore read the responses in the right order? Or is there a = possibility that, say, thread three will get the response that should = have been for thread one? Is this something I need to take into = consideration, and if so, how? Real-world problem: While as I said this system worked well in testing, = Now that I have gotten it out into production I've occasionally run into = a problem where the master thread waiting for a response on master_queue = times out while waiting. This causes a (potentially) two-fold problem, = in that first off the master process doesn't get the information it had = requested, and secondly that I *could* end up with an "orphaned" message = on the queue that could cause problems the next time I try to read = something from it. I currently have the timeout set to 3 seconds. I can, of course, = increase that, but that could lead to a bad user experience - and might = not even help the situation if something else is going on. The actual = exchange is quite simple: On the master side, I have this code: config.socket_queue.put('GET_PORT') try: port =3D config.master_queue.get(timeout=3D3) #wait up to three = seconds for a response except Empty: port =3D 5000 # default. Can't hurt to try. Which, as you might have been able to guess, tries to ask the child = process (an instance of a tornado server, btw) what port it is listening = on. The child process then, on getting this message from the queue, runs = the following code: elif item =3D=3D 'GET_PORT': port =3D utils.config.getint('global', 'tornado.port') master_queue.put(port) So nothing that should take any significant time. Of course, since this = is a single thread handling any number of requests, it is possible that = the thread is tied up responding to a different request (or that the GIL = is preventing the thread from running at all, since another thread might = be commandeering the processor), but I find it hard to believe that it = could be tied up for more than three seconds. So is there a better way to do sub-process bi-directional communication = that would avoid these issues? Or do I just need to increase the timeout = (or remove it altogether, at the risk of potentially causing the thread = to hang if no message is posted)? And is my concern justified, or just = paranoid? Thanks for any information that can be provided! ----------------------------------------------- Israel Brewster Systems Analyst II Ravn Alaska 5245 Airport Industrial Rd Fairbanks, AK 99709 (907) 450-7293 -----------------------------------------------