竞争条件怎么会导致 p[0] 成为 None 呢?

How could a race condition cause p[0] to be None here?

这是我的(相当冗长的)函数:

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被打印出来。这是为什么?

因为你有一个竞争条件..你在调用 Popen 之前启动定时器(超时)并将 p[0] 设置为非 None 值。如果子进程未设置并且 return Popen 对象在定时器触发之前,您将在尝试终止进程时看到 p[0] 是 None。

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

当这个 运行s:

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

你发起了一个新话题。然后 OS 可能会抢占您当前的线程并 运行 新线程一段时间(或者 运行 在其他进程中系统上的任何其他线程 运行 就此而言)。如果系统很忙或者你很不走运,有可能你的线程被抢占的时间超过timeout。在填充 p[0].

之前,您不应该启动计时器