您对问题的描述表明,父进程中的后台线程继续存在,并在子进程中执行。这是不可能的;至少,在POSIX系统上是不可能的。在你的案子里发生的是另外一件事。下面我将对此进行一些推测,然后提出如何避免这个问题的建议。轮流把这些要点。。。

1。只有一个线程可以分叉。

分叉之后,只有调用fork()的线程仍然是活动的。下面是一个小示例,说明其他线程不会在子进程中继续执行:def output():

time.sleep(3)
print "Thread executing in process: %d" % os.getpid()
thread = threading.Thread(target=output)
thread.start()
os.fork()
print "Pid: %d" % os.getpid()

您将看到父线程和子线程都将其pid打印到stdout,但是第二个线程只在父线程中生成输出。

所以让监控线程检查它的pid或者以其他方式检查它在哪个进程中运行的情况不会有什么不同;该线程只在一个进程中执行。

2。分叉在某些方面会导致问题,如您所见。

分叉可以以各种方式导致程序状态的损坏。例如:线程中引用的由于分叉而死亡的对象可能超出范围,因此调用了它们的终结器。例如,如果这样一个对象表示一个网络资源,并且调用它的del方法会导致连接的一端意外关闭,这可能会导致问题。

任何缓冲IO都会导致问题,因为缓冲区在子进程中是重复的。

注意第二点甚至不需要线程。考虑以下因素:

^{pr2}$

我们向testfile写入了一个字符,并在分叉之前在父对象中这样做了。但我们在内容未刷新的情况下分岔,因此:alp:~ $ wc -c testfile

2 testfile

文件包含两个字符,因为输出缓冲区被复制到子级,父级和子级最终都刷新了它们的缓冲区。

我怀疑你的问题是由第二个问题引起的(尽管我很高兴地承认这纯粹是猜测)。

3。重新设计以避免此类问题。

您在一条评论中提到,在生成工作线程后无法启动监视线程,因为您需要反复创建新的工作线程。为了避免这种情况,重组你正在做的事情可能比你想象的要容易。不是为每个新的工作单元生成一个进程,而是创建一组由控制进程管理的长寿命工人:控制器向队列提供需要处理的作业的规范;它在空闲时这样做。每个工作线程都会无限循环,在作业到达队列时从队列中提取作业并执行它们。(来自multiprocessing的队列实现将保证每个作业描述仅由一个worker绘制)因此,您只需要在早期生成一次worker,并且可以在所有分叉完成后创建监视线程。

下面是这种组织的示意图:

from multiprocessing import Process, Queue
def work(q):
while True:
job = q.get()
if job is None:
# We've been signaled to stop.
break
do_something_with(job)
queue = Queue()
NUM_WORKERS = 3
NUM_JOBS = 20
# Start workers.
for _ in range(NUM_WORKERS):
p = Process(target=work, args=(queue,))
p.start()
# Create your monitor thread here.
# Put work in the queue. This continues as long as you want.
for i in range(NUM_JOBS):
queue.put(i)
# When there's no more work, put sentinel values in the queue so workers
# know to gracefully exit.
for _ in range(NUM_WORKERS):
queue.put(None)