我试图在一些工作时间后彻底退出,因为线程被某些东西阻挡了。我正在使用这样的repo=$1
relBranch=$2
branchStart=$3
workDir=${repo}-closeout-`date +"%Y-%m-%d"`
git clone .../${repo}.git ${workDir}
pushd ${workDir}
# update release branch
git checkout ${relBranch}; git pull
# create branch from branch start
git checkout ${branchStart} -b squash/${relBranch}
# Squash Merge branch history into single commit
git clean -d -f -x .
git merge --squash ${relBranch}
# check that status reports only staged changes
git commit -m "release/0.9 squash ${branchStart}..HEAD"
squashedCommit=`git log --format="%H" -n 1`
# Prepare master
git checkout master; git pull
# create staging branch for delta check
git checkout -b deltacheck/${relBranch}
git clean -d -f -x .
# check release branch history delta
git cherry-pick --no-commit ${squashedCommit}
git status
# Diff
git diff
popd
:
ThreadPoolExecutor
此代码到try:
with concurrent.futures.ThreadPoolExecutor(max_workers=32) as executor:
# submit some work
workers = [executor.submit(...) for x in work]
# wait for completion
try:
for f in concurrent.futures.as_completed(workers, timeout=60):
f.result()
except concurrent.futures.TimeoutError:
raise TimeoutError()
except TimeoutError:
# cleanup
没问题,但脚本永远不会退出,因为它正在等待被阻止的线程最终完成。我还不知道是什么导致工人永远阻止,这是另一个需要解决的问题,但是当我们遇到这种情况时,我需要有办法至少退出。
我看了ThreadPoolExecutor中的线程是如何创建的,并且它们被设置为# cleanup
所以我更加困惑为什么这些线程阻止应用程序退出。
答案 0 :(得分:3)
奇怪的是,这是预期的行为。来自concurrent/futures/thread.py
(版本3.6.3):
# To work around this problem, an exit handler is installed which tells the
# workers to exit when their work queues are empty and then waits until the
# threads finish.
"这个问题"正是您想要的行为 - 在工作线程仍在运行时退出。提到的退出处理程序在所有工作线程上调用join()
,如果它们被卡住则会永久阻塞:
def _python_exit():
global _shutdown
_shutdown = True
items = list(_threads_queues.items())
for t, q in items:
q.put(None)
for t, q in items:
t.join()
atexit.register(_python_exit)
还有__exit__
本身的TaskThreadExecutor
方法:
def __exit__(self, exc_type, exc_val, exc_tb):
self.shutdown(wait=True)
return False
带有self.shutdown
的 wait=True
也加入了所有工作线程。
要强制退出,我们需要覆盖这两个。如果您按如下方式修改代码:
except concurrent.futures.TimeoutError:
import atexit
atexit.unregister(concurrent.futures.thread._python_exit))
executor.shutdown = lambda wait:None
raise TimeoutError()
然后您的脚本将根据需要退出。