Python错误“无法启动新线程”,但没有其他线程在运行

时间:2018-04-19 10:55:47

标签: python multithreading python-multithreading

我有一个用Python 2.7编写的守护进程,它的工作原理如下:

  

1 - 脚本启动4个线程

     

2 - 4个线程正在同时做一些工作

     

3 - 脚本使用thread.join()

等待所有线程完成      

4 - 1-3 in a loop

在伪代码中,它看起来像:

formatter = logging.Formatter('%(threadName)s : %(message)s')
# (... logging setup ...)
def doSomeWork(item):
    log.debug('Doing some work with item %s', item)
    # (... doing some work ...)
itemList = [some, items, thatProgram, worksWith]
while True:
    threads = []
    for item in itemList:
        if someComplexConditionCheck:
             threads.append(threading.Thread(target=doSomeWork, args=(item,))
    for thread in threads:
        thread.start()
    for thread in threads:
        thread.join()
    time.sleep(10)

(当然,真正的程序要复杂得多) (真正的doSomeWork代码可能会启动一些其他线程,但它也使用thread.join()来等待完成)。主要的while(true)循环将永远不会继续,直到所有先前的线程完成。

几天后我的程序崩溃了“错误:无法启动新线程”。日志中的最后一条记录对应于线程15027,它看起来像:

Thread-15027 Doing some work

我查找了stackoverflow,但我发现的所有建议都是使用命令ps -fLu UserName检查一次运行的线程数。 我看到只有线程在检查时运行,因此较旧的线程总是在启动new之前完成因为join命令。

我认为,问题可能在于大线程id(15027),它在每次调用Thread构造函数后都会增加。 (我是对的吗?)但我不知道如何重置它,但每天使用crontab重启守护进程,但这是一个非常脏的黑客。

1 个答案:

答案 0 :(得分:0)

由于问题与线程创建无直接关系,您可以检查内存是否用完了吗?这似乎是最可能的罪魁祸首。但是,无论原因如何,一种验证方法是在strace下运行您的应用程序并查找ENOMEM错误或任何其他错误。

我最初的想法是让你的应用程序检查可用内存,但是从应用程序执行此操作变得棘手,因为操作系统有时会使用大量可用内存,然后在应用程序需要时放弃它。

  

strace -o app_strace.log python app.py myarg1 myarg2

如果出现错误,POSIX系统调用通常会返回-1,因此您可以grep日志文件

  

grep“\ = -1”app_strace.log