windows - Stopping the execution of threads in Python. The thread is blocked before join method -


i'm writing program execute child programs in new process , read stdout of these programs in separate thread , write in styledtextctrl control. faced problem of stopping execution of threads. have following code:

import subprocess threading import thread, lock import wx import wx.stc   import logging logging.basicconfig(level=logging.debug,                     format='[%(levelname)s] (%(threadname)-10s) %(module)10s:%(funcname)-15s %(message)s',                     )  class readthread(thread):     def __init__(self, subp, fd, append_text_callback):         thread.__init__(self)         self.killed = false         self.subp = subp         self.fd = fd         self.append_text_callback = append_text_callback      def run(self):         chunk = none         while chunk != '' , not self.killed:             self.subp.poll()             chunk = self.fd.readline()             if chunk:                 self.append_text_callback('%d: ' % self.subp.pid + chunk)             if chunk == "":                 break         logging.debug('end')   class myform(wx.frame):      def __init__(self):         wx.frame.__init__(self, none, wx.id_any, "example1")         panel = wx.panel(self, wx.id_any)         self.log = wx.stc.styledtextctrl(panel, wx.id_any, size=(300,100), style=wx.te_multiline|wx.te_readonly|wx.hscroll)         run_button = wx.button(panel, wx.id_any, 'run')         self.bind(wx.evt_button, self.onrun, run_button)         self.bind(wx.evt_close, self.oncloseframe)         sizer = wx.boxsizer(wx.vertical)         sizer.add(self.log, 1, wx.all|wx.expand, 5)         sizer.add(run_button, 0, wx.all|wx.center, 5)         panel.setsizer(sizer)         self.read_thread_1 = none         self.read_thread_2 = none         self.log_lock = lock()                  def oncloseframe(self, event):         logging.debug('close')         if self.read_thread_1:             self.read_thread_1.killed = true         if self.read_thread_2:             self.read_thread_2.killed = true         if self.read_thread_1:             self.read_thread_1.join(timeout=1)             logging.debug('after 1 join')         if self.read_thread_2:             self.read_thread_2.join(timeout=1)             logging.debug('after 2 join')         self.read_thread_1 = none         self.read_thread_2 = none         event.skip()      def onrun(self, event):         cmd1 = "e:/threading_block/stdout_emulator.exe 50 500"         subp1 = subprocess.popen(cmd1, stdout=subprocess.pipe, stderr=subprocess.pipe)         self.read_thread_1 = readthread(subp1, subp1.stdout, self.appendtext)         self.read_thread_1.start()         cmd2 = "e:/threading_block/stdout_emulator.exe 21 400"         sp2 = subprocess.popen(cmd2, stdout=subprocess.pipe, stderr=subprocess.pipe)         self.read_thread_2 = readthread(sp2, sp2.stdout, self.appendtext)         self.read_thread_2.start()         logging.debug('end')      def appendtext(self, text):         self.log_lock.acquire()         logging.debug('%s' % text)         self.log.addtext(text)         self.log_lock.release()  if __name__ == "__main__":     app = wx.pysimpleapp()     frame = myform().show()     app.mainloop() 

i stop threads in oncloseframe method. set killed attribute in true value , result cause finishing execution of while loop in run method of readthread class. there no problem when close application (under windows) during execution of threads. if remove timeout=1 self.read_thread_1.join(timeout=1) , self.read_thread_2.join(timeout=1) there blocking of program.

the program stuck before self.read_thread_1.join() in oncloseframe method.

what's problem blocking? why should use timeout join?

the c code of std_emulator.exe following:

#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <time.h>  int main(int argc, char *argv[]) {   int s;   int n;   if (argc > 1)   {         s = atoi(argv[1]);     n = atoi(argv[2]);   }   else   {     s = 1;     n = 50;   }    int i;   (i = s; < n; ++i)   {     printf("this %d line\n", i);     fflush(stdout);     if (i % 2 == 0)      {              srand(time(null));       int r = rand() % 7;       printf("sleep_type_2 %d\n", r);       sleep(30 * r);       fflush(stdout);      }            if (i % 3 == 0)        {              int r = rand() % 7;         printf("sleep_type_3 %d\n", r);         sleep(40 * r);         fflush(stdout);        }       if (i % 5 == 0)        {         int r = rand() % 9;         printf("sleep_type_5 %d\n", r);         sleep(50);         fflush(stdout);        }        } } 

in case, you're not killing threads when use join(timeout=1). instead, join operation waiting 1 second see if thread exits, , when doesn't, gives up. join won't work because thread blocking on line:

chunk = self.fd.readline() 

so it's never looping around see if killed has been set true. think best way cleanly shutdown threads terminate subprocess being run in readthread in oncloseframe:

if self.read_thread_1:     self.read_thread_1.subp.terminate()     self.read_thread_1.join() if self.read_thread_2:     self.read_thread_2.subp.terminate()     self.read_thread_2.join() 

terminating subprocess unblock readline call, , allow cleanly terminate thread.


Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -