竞争条件如何导致p [0]为无?

时间:2015-10-02 16:04:36

标签: python linux multithreading ctypes python-multithreading

这是我的(相当冗长的)功能:

def go(self, target, outfile, infile, stderr=sys.stderr, timeout=None):        

    self.pre_proc_started()                                                    
    try:                                                                       
        infile_fileno = infile.fileno()                                        
    except AttributeError:                                                     
        infile_fileno = None                                                   
    p_stdin = infile if infile_fileno is not None else subprocess.PIPE         

    if timeout is not None:                                                    
        p = [None]                                                             
        def kill_process(p):                                                   
            if p[0]:                                                           
                p[0].kill()                                                    
            else:                                                              
                print("WTH")                                                   
        timer = threading.Timer(timeout, lambda: kill_process(p))              
        timer.start()                                                          

    p[0] = subprocess.Popen(target, stdin=p_stdin, stderr=stderr,              
                            env={'__AFL_SHM_ID': str(self.shm_id)})            
    try:                                                                       
        if p_stdin == subprocess.PIPE:                                         
            p[0].stdin.write(infile.read())                                    
            p[0].stdin.close()                                                 
    except IOError:  # brobably broken pipe                                    
        raise                                                                  
    p[0].wait()                                                                
    if timeout is not None:                                                    
        timer.cancel()                                                         
    self.post_proc_started()                                                   

    trace_bytes_addr = shmat(self.shm_id, 0, 0)                                
    if trace_bytes_addr == 2**64 - 1:                                          
        raise RuntimeError("shmat() failed (%s)" % os.strerror(errno()))       
    trace_bytes = ctypes.string_at(ctypes.c_void_p(trace_bytes_addr),          
                                   MAP_SIZE)                                   
    return trace_bytes                         

为什么我觉得很难相信,如果我运行足够多次,p[0]None,我就会打印WTH。那是为什么?

2 个答案:

答案 0 :(得分:1)

因为你有竞争条件..你在调用Popen之前启动Timer(带超时)并将p [0]设置为非None值。如果子进程在Timer触发之前没有设置并返回Popen对象,则当您尝试终止进程时,您将看到p [0]为None。

确保您的超时值足够高或等到您在启动计时器之前调用Popen之后。

答案 1 :(得分:1)

运行时:

timer = threading.Timer(timeout, lambda: kill_process(p))              
timer.start()

你启动一个新线程。然后,OS可以抢占您当前的线程并运行新线程一段时间(或者在其他进程中在系统上运行的任何其他线程)。如果系统非常繁忙或您非常不走运,那么您的线程可能会被抢占的时间超过timeout。在您填充p[0]之前,您不应该启动计时器。