竞争条件怎么会导致 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]
.
之前,您不应该启动计时器
这是我的(相当冗长的)函数:
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]
.