ℹ️ Skipped - page is already crawled
| Filter | Status | Condition | Details |
|---|---|---|---|
| HTTP status | PASS | download_http_code = 200 | HTTP 200 |
| Age cutoff | PASS | download_stamp > now() - 6 MONTH | 6.7 months ago (distributed domain, exempt) |
| History drop | PASS | isNull(history_drop_reason) | No drop reason |
| Spam/ban | PASS | fh_dont_index != 1 AND ml_spam_score = 0 | ml_spam_score=0 |
| Canonical | PASS | meta_canonical IS NULL OR = '' OR = src_unparsed | Not set |
| Property | Value |
|---|---|
| URL | https://github.com/python/cpython/issues/63166 |
| Last Crawled | 2025-09-28 00:58:07 (6 months ago) |
| First Indexed | 2022-04-13 03:29:53 (4 years ago) |
| HTTP Status Code | 200 |
| Meta Title | Threads within multiprocessing Process terminate early · Issue #63166 · python/cpython |
| Meta Description | BPO 18966 Nosy @tim-one, @pitrou, @bitdancer, @eryksun, @applio PRs #3111 Files processthread.py: Test program Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state. Show mo... |
| Meta Canonical | null |
| Boilerpipe Text | Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state. Show more details GitHub fields: assignee = None closed_at = < Date 2017 - 08 - 16.18 : 54 : 02.032 > created_at = < Date 2013 - 09 - 08.01 : 20 : 27.821 > labels = [ '3.7' , 'type-feature' , 'library' ]
title = 'Threads within multiprocessing Process terminate early' updated_at = < Date 2017 - 08 - 16.18 : 54 : 02.031 > user = 'https://bugs.python.org/pietvo' bugs.python.org fields: activity = < Date 2017 - 08 - 16.18 : 54 : 02.031 > actor = 'pitrou' assignee = 'none' closed = True closed_date = < Date 2017 - 08 - 16.18 : 54 : 02.032 > closer = 'pitrou' components = [ 'Library (Lib)' ]
creation = < Date 2013 - 09 - 08.01 : 20 : 27.821 > creator = 'pietvo' dependencies = []
files = [ '31658' ]
hgrepos = []
issue_num = 18966 keywords = []
message_count = 17.0 messages = [ '197210' , '197293' , '270338' , '270343' , '270351' , '270352' , '270353' , '270355' , '270375' , '270382' , '270415' , '270419' , '270421' , '270422' , '270433' , '300385' , '300386' ]
nosy_count = 8.0 nosy_names = [ 'tim.peters' , 'pitrou' , 'r.david.murray' , 'pietvo' , 'neologix' , 'sbt' , 'eryksun' , 'davin' ]
pr_nums = [ '3111' ]
priority = 'normal' resolution = 'fixed' stage = 'resolved' status = 'closed' superseder = None type = 'enhancement' url = 'https://bugs.python.org/issue18966' versions = [ 'Python 3.7' ] |
| Markdown | [Skip to content](https://github.com/python/cpython/issues/63166#start-of-content)
## Navigation Menu
Toggle navigation
[Sign in](https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fcpython%2Fissues%2F63166)
Appearance settings
- Platform
- [GitHub Copilot Write better code with AI](https://github.com/features/copilot)
- [GitHub Spark New Build and deploy intelligent apps](https://github.com/features/spark)
- [GitHub Models New Manage and compare prompts](https://github.com/features/models)
- [GitHub Advanced Security Find and fix vulnerabilities](https://github.com/security/advanced-security)
- [Actions Automate any workflow](https://github.com/features/actions)
- [Codespaces Instant dev environments](https://github.com/features/codespaces)
- [Issues Plan and track work](https://github.com/features/issues)
- [Code Review Manage code changes](https://github.com/features/code-review)
- [Discussions Collaborate outside of code](https://github.com/features/discussions)
- [Code Search Find more, search less](https://github.com/features/code-search)
Explore
- [Why GitHub](https://github.com/why-github)
- [Documentation](https://docs.github.com/)
- [GitHub Skills](https://skills.github.com/)
- [Blog](https://github.blog/)
Integrations
- [GitHub Marketplace](https://github.com/marketplace)
- [MCP Registry](https://github.com/mcp)
[View all features](https://github.com/features)
- Solutions
By company size
- [Enterprises](https://github.com/enterprise)
- [Small and medium teams](https://github.com/team)
- [Startups](https://github.com/enterprise/startups)
- [Nonprofits](https://github.com/solutions/industry/nonprofits)
By use case
- [App Modernization](https://github.com/solutions/use-case/app-modernization)
- [DevSecOps](https://github.com/solutions/use-case/devsecops)
- [DevOps](https://github.com/solutions/use-case/devops)
- [CI/CD](https://github.com/solutions/use-case/ci-cd)
- [View all use cases](https://github.com/solutions/use-case)
By industry
- [Healthcare](https://github.com/solutions/industry/healthcare)
- [Financial services](https://github.com/solutions/industry/financial-services)
- [Manufacturing](https://github.com/solutions/industry/manufacturing)
- [Government](https://github.com/solutions/industry/government)
- [View all industries](https://github.com/solutions/industry)
[View all solutions](https://github.com/solutions)
- Resources
Topics
- [AI](https://github.com/resources/articles/ai)
- [DevOps](https://github.com/resources/articles/devops)
- [Security](https://github.com/resources/articles/security)
- [Software Development](https://github.com/resources/articles/software-development)
- [View all](https://github.com/resources/articles)
Explore
- [Learning Pathways](https://resources.github.com/learn/pathways)
- [Events & Webinars](https://github.com/resources/events)
- [Ebooks & Whitepapers](https://github.com/resources/whitepapers)
- [Customer Stories](https://github.com/customer-stories)
- [Partners](https://github.com/partners)
- [Executive Insights](https://github.com/solutions/executive-insights)
- Open Source
- [GitHub Sponsors Fund open source developers](https://github.com/sponsors)
- [The ReadME Project GitHub community articles](https://github.com/readme)
Repositories
- [Topics](https://github.com/topics)
- [Trending](https://github.com/trending)
- [Collections](https://github.com/collections)
- Enterprise
- [Enterprise platform AI-powered developer platform](https://github.com/enterprise)
Available add-ons
- [GitHub Advanced Security Enterprise-grade security features](https://github.com/security/advanced-security)
- [Copilot for business Enterprise-grade AI features](https://github.com/features/copilot/copilot-business)
- [Premium Support Enterprise-grade 24/7 support](https://github.com/premium-support)
- [Pricing](https://github.com/pricing)
Search or jump to...
# Search code, repositories, users, issues, pull requests...
[Search syntax tips](https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax)
# Provide feedback
Cancel
Submit feedback
# Saved searches
## Use saved searches to filter your results more quickly
Cancel
Create saved search
[Sign in](https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fcpython%2Fissues%2F63166)
[Sign up](https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=python%2Fcpython)
Appearance settings
Resetting focus
You signed in with another tab or window. [Reload](https://github.com/python/cpython/issues/63166) to refresh your session. You signed out in another tab or window. [Reload](https://github.com/python/cpython/issues/63166) to refresh your session. You switched accounts on another tab or window. [Reload](https://github.com/python/cpython/issues/63166) to refresh your session.
Dismiss alert
{{ message }}
[python](https://github.com/python) / **[cpython](https://github.com/python/cpython)** Public
- Sponsor
# Sponsor python/cpython
##### GitHub Sponsors
[Learn more about Sponsors](https://github.com/sponsors)
[](https://github.com/python)
[python](https://github.com/python)
[python](https://github.com/python)
[Sponsor](https://github.com/sponsors/python)
##### External links
<https://www.python.org/psf/donations/python-dev/>
[Learn more about funding links in repositories](https://docs.github.com/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository).
[Report abuse](https://github.com/contact/report-abuse?report=python%2Fcpython+%28Repository+Funding+Links%29)
- [Notifications](https://github.com/login?return_to=%2Fpython%2Fcpython)
You must be signed in to change notification settings
- [Fork 33k](https://github.com/login?return_to=%2Fpython%2Fcpython)
- [Star 69.1k](https://github.com/login?return_to=%2Fpython%2Fcpython)
- [Code](https://github.com/python/cpython)
- [Issues 5k+](https://github.com/python/cpython/issues)
- [Pull requests 2.1k](https://github.com/python/cpython/pulls)
- [Actions](https://github.com/python/cpython/actions)
- [Projects 28](https://github.com/python/cpython/projects)
- [Security](https://github.com/python/cpython/security)
[Uh oh\!](https://github.com/python/cpython/security)
[There was an error while loading.](https://github.com/python/cpython/security) [Please reload this page](https://github.com/python/cpython/issues/63166).
- [Insights](https://github.com/python/cpython/pulse)
Additional navigation options
- [Code](https://github.com/python/cpython)
- [Issues](https://github.com/python/cpython/issues)
- [Pull requests](https://github.com/python/cpython/pulls)
- [Actions](https://github.com/python/cpython/actions)
- [Projects](https://github.com/python/cpython/projects)
- [Security](https://github.com/python/cpython/security)
- [Insights](https://github.com/python/cpython/pulse)
# Threads within multiprocessing Process terminate early \#63166
[New issue](https://github.com/login?return_to=https://github.com/python/cpython/issues/63166)
Copy link
[New issue](https://github.com/login?return_to=https://github.com/python/cpython/issues/63166)
Copy link
Closed
Closed
[Threads within multiprocessing Process terminate early](https://github.com/python/cpython/issues/63166#top)
\#63166
Copy link
Labels
[3\.7 (EOL)end of life](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%223.7%20\(EOL\)%22)end of life[stdlibStandard Library Python modules in the Lib/ directory](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22stdlib%22)Standard Library Python modules in the Lib/ directory[type-featureA feature request or enhancement](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-feature%22)A feature request or enhancement
[]()
## Description
[]()
[pietvo]()
mannequin
opened
[on Sep 8, 2013](https://github.com/python/cpython/issues/63166#issue-1198904829)
Mannequin
Issue body actions
| BPO | [18966](https://bugs.python.org/issue18966) |
|---|---|
| Nosy | [@tim-one](https://github.com/tim-one), [@pitrou](https://github.com/pitrou), [@bitdancer](https://github.com/bitdancer), [@eryksun](https://github.com/eryksun), [@applio](https://github.com/applio) |
| PRs | [bpo-18966: non-daemonic threads created by a multiprocessing.Process should be joined on exit \#3111](https://github.com/python/cpython/pull/3111) |
*Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.*
Show more details
GitHub fields:
```
assignee = None
closed_at = <Date 2017-08-16.18:54:02.032>
created_at = <Date 2013-09-08.01:20:27.821>
labels = ['3.7', 'type-feature', 'library']
title = 'Threads within multiprocessing Process terminate early'
updated_at = <Date 2017-08-16.18:54:02.031>
user = 'https://bugs.python.org/pietvo'
```
bugs.python.org fields:
```
activity = <Date 2017-08-16.18:54:02.031>
actor = 'pitrou'
assignee = 'none'
closed = True
closed_date = <Date 2017-08-16.18:54:02.032>
closer = 'pitrou'
components = ['Library (Lib)']
creation = <Date 2013-09-08.01:20:27.821>
creator = 'pietvo'
dependencies = []
files = ['31658']
hgrepos = []
issue_num = 18966
keywords = []
message_count = 17.0
messages = ['197210', '197293', '270338', '270343', '270351', '270352', '270353', '270355', '270375', '270382', '270415', '270419', '270421', '270422', '270433', '300385', '300386']
nosy_count = 8.0
nosy_names = ['tim.peters', 'pitrou', 'r.david.murray', 'pietvo', 'neologix', 'sbt', 'eryksun', 'davin']
pr_nums = ['3111']
priority = 'normal'
resolution = 'fixed'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue18966'
versions = ['Python 3.7']
```
## Activity
[]()
### pietvo commented on Sep 8, 2013
[]()
[pietvo]()mannequin
[on Sep 8, 2013](https://github.com/python/cpython/issues/63166#issuecomment-1093627174)
MannequinAuthor
More actions
When a process started as a multiprocessing Process spawns a thread, it doesn't wait until the thread terminates. It terminates the thread early when the main thread of the process terminates, as if the thread would be daemonic (it isn't).
It may sound a bit weird to start a Thread within multiprocessing, but it isn't prohibited. Neither is this behavior documented.
In the attached program the thread doesn't complete. However when the mythread.join() statement is uncommented it does run to completion.
[pietvo]()
added
[type-bugAn unexpected behavior, bug, or error](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-bug%22)An unexpected behavior, bug, or error
[stdlibStandard Library Python modules in the Lib/ directory](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22stdlib%22)Standard Library Python modules in the Lib/ directory
[on Sep 8, 2013](https://github.com/python/cpython/issues/63166#event-6403189483)
[](https://github.com/pitrou)
### pitrou commented on Sep 8, 2013
[](https://github.com/pitrou)
[pitrou](https://github.com/pitrou)
[on Sep 8, 2013](https://github.com/python/cpython/issues/63166#issuecomment-1093627175)
Member
More actions
That's because multiprocessing exits child processes with os.\_exit(), not sys.exit().
The fix would be trivial (call threading.\_shutdown() before os.\_exit()), but I don't know if that's something we want to do. After all there are many things in the Python shutdown procedure that we may want to similarly replicate in multiprocessing children, such as calling atexit handlers. This screams for a more general solution, IMHO.
[](https://github.com/tim-one)
### tim-one commented on Jul 13, 2016
[](https://github.com/tim-one)
[tim-one](https://github.com/tim-one)
[on Jul 13, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627176)
Member
More actions
This came up again today as bug 27508. In the absence of "fixing it", we should add docs to multiprocessing explaining the high-level consequences of skipping "normal" exit processing (BTW, I'm unclear on why it's skipped).
I've certainly mixed threads with multiprocessing too, but I always explicitly .join() my threads so never noticed this. It's sure a puzzle when it happens ;-)
[](https://github.com/eryksun)
### eryksun commented on Jul 13, 2016
[](https://github.com/eryksun)
[eryksun](https://github.com/eryksun)
[on Jul 13, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627177)
Contributor
More actions
In 3.4+ it works correctly with the "spawn" start method. This uses multiprocessing.spawn.spawn\_main, which exits the child via sys.exit(exitcode). "fork" and "forkserver" exit the child via os.\_exit(code), respectively in multiprocessing.popen\_fork.Popen.\_launch and multiprocessing.forkserver.main.
[](https://github.com/applio)
### applio commented on Jul 14, 2016
[](https://github.com/applio)
[applio](https://github.com/applio)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627180)
Member
More actions
It is a general rule that when a process terminates, it likewise terminates all its threads (unless a thread has been explicitly detached). How it goes about doing so is complicated.
Remember that POSIX threads have no concept of parent/child among themselves and all threads are viewed as a single pool. The section "No parents, no children" at
<http://www.ibm.com/developerworks/library/l-posix1/> offers us motivation for why waiting on a pthread should be explicitly requested and not assumed as a default behavior.
There are numerous differences between what a UNIX-style process and a win32 process does at termination. Though an older post from Microsoft, a strong sense of how complicated the process-termination-begets-thread-termination truly is can be had from reading <https://blogs.msdn.microsoft.com/oldnewthing/20070503-00/?p=27003> which also helps reinforce the sentiment above (needs explicit instructions on what to do, no general solution can exist). Whereas the prior provided some sense of motivation, this link walks us through ugly complications and consequences that arise.
The short of it is that the current use of os.\_exit() is most appropriate in multiprocessing. Threads should be signaled that the process is terminating but we are not generally expected to wait on those threads.
These and many other reference-worthy links help support the call for atexit-like functionality to be exposed on multiprocessing.Process. There have been multiple issues opened on the bug tracker ultimately requesting this enhancement (do a search for multiprocessing and atexit). I think it's a very sensible enhancement (Antoine did too and perhaps still does) and worth taking the time to pursue. As an aside, I wonder if an equivalent to pthread\_cleanup\_push should also be exposed on threading.Thread.
When it comes to documentation, I am of two minds. There seem to be an increasing number of people coming to Python without much prior exposure to the concepts of threads and processes and so it would be wrong for us to ignore this reality. On the flip side, attempting to convey all the core concepts of threads and processes and how they interact would result in a large documentation effort that ultimately few people would eagerly read to completion. Adding a one-sentence caveat hiding somewhere in the docs won't do much to help. Given this topic and a few other issues that have come up very recently, I suggest that a concise paragraph be added on the topic of using threads and processes together -- likely placed at the beginning of the docs on the Process class. I think I'm up for taking a crack at that but I'd very much appreciate critical eyes to review it with me.
Per Eryk's point about the difference in multiprocessing's behavior when using spawn vs. fork, the explanation for why it's done that way is also described in the DeveloperWorks article I mentioned above.
Finally, per the original post from pietvo for future readers, not only is it \*not\* weird to start a Thread within a Process, it's a popular and useful technique.
[](https://github.com/tim-one)
### tim-one commented on Jul 14, 2016
[](https://github.com/tim-one)
[tim-one](https://github.com/tim-one)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627182)
Member
More actions
Devin, a primary point of `threading.py` is to provide a sane alternative to the cross-platform thread mess. None of these reports are about making it easier for threads to go away "by magic" when the process ends. It's the contrary: they're asking for multiprocessing to respect threading.py's default behavior of making it the programmer's responsibility to shut down their threads cleanly. "Shut down your threads, or we refuse to let the process end."
It doesn't matter that native OS threads may behave differently. threading.py very deliberately makes \_its\_ thread abstraction "non-daemonic" by default, and advertises that behavior for all platforms. So it's at best surprising that threading.Thread's default semantics get turned inside out when multiprocessing creates a process. I still see no reason to believe that's "a feature".
As to docs, if it boils down to the difference between `sys.exit()` and `os._exit()`, then *those* are the places to put details, and multiprocessing docs just need to point out when a created process will use one or the other.
As is, the docs don't contain the slightest clue anywhere that a threading.Thread may violate its own docs (with respect to process-exit behavior) when created by a process launched by multiprocessing (or also by a concurrent.futures.ProcessPoolExecutor? I didn't check).
[](https://github.com/eryksun)
### eryksun commented on Jul 14, 2016
[](https://github.com/eryksun)
[eryksun](https://github.com/eryksun)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627183)
Contributor
More actions
> Per Eryk's point about the difference in multiprocessing's behavior
> when using spawn vs. fork, the explanation for why it's done that
> way is also described in the DeveloperWorks article I mentioned above.
Please spell this out for me. Why can't the "fork" and "forkserver" variations call sys.exit(), and thus Py\_Finalize? I don't see why it's OK to call the \_shutdown function in [Lib/threading.py](https://github.com/python/cpython/blob/main/Lib/threading.py) from a spawned child but not a forked child.
[](https://github.com/tim-one)
### tim-one commented on Jul 14, 2016
[](https://github.com/tim-one)
[tim-one](https://github.com/tim-one)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627184)
Member
More actions
About ""No parents, no children", that's fine so far as it goes. But Python isn't C, a threading.Thread is not a POSIX thread, and threading.py \_does\_ have a concept of "the main thread". There's no conceptual problem \_in Python\_ with saying "the main thread" waits to .join() other non-daemon threading.Threads at process exit. No parent/child relationships are implied by that either - it's just the concept that one thread is distinguished.
[](https://github.com/pitrou)
### pitrou commented on Jul 14, 2016
[](https://github.com/pitrou)
[pitrou](https://github.com/pitrou)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627185)
Member
More actions
I agree with Tim. Regardless of what OS threads do, Python tries to enforce predictable semantics of its own. There's no reason (apart from historical baggage) to not join Python threads (and only Python threads, of course, not other OS threads) at the shutdown of a child process.
I don't exactly remember why using os.\_exit() rather than sys.exit() is required in child processes. Presumably it is because we don't want the child to clobber any resources shared with the parent (open files?). This doesn't have to be a binary thing, though: it may as well be os.\_exit() + a bunch of cleanup steps we know are safe to perform.
[pitrou](https://github.com/pitrou)
added
[type-featureA feature request or enhancement](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-feature%22)A feature request or enhancement
and removed
[type-bugAn unexpected behavior, bug, or error](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-bug%22)An unexpected behavior, bug, or error
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#event-6403189485)
[]()
### neologix commented on Jul 14, 2016
[]()
[neologix]()mannequin
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627187)
Mannequin
More actions
One reason for not calling sys.exit() is because on Linux, the default
implementation uses fork(), hence the address space in the chilren is
a clone of the parent: so all atexit handlers, for example, would be
called multiple times.
There's also the problem that fork() isn't MT-safe, making the
probability of screwups/deadlocks in various destructors/stack
unwinding greater.
[](https://github.com/applio)
### applio commented on Jul 14, 2016
[](https://github.com/applio)
[applio](https://github.com/applio)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627188)
Member
More actions
Tim: Totally agreed about threading.Thread not being a POSIX thread. It was not my intent to suggest that they were equivalent -- apologies for the confusion.
Instead I was attempting to describe a mentality of processes and their common behavior across multiple platforms at termination. The behavior of child processes via multiprocessing currently appears to follow this common mentality of signal the threads then exit quickly. (To avoid confusion, I am making an observation here.)
Whereas threading.Thread is attempting to provide something homogeneous across platforms, achieving a similar goal in multiprocessing.Process is complicated by the concepts of fork vs. spawn and their availability on various OSes (a source of real confusion for some). This further opens the question of what should the mentality be for multiprocessing.Process? The notion that a process can die in such a way that not all of its threads were given time to clean up does not strike me as a foreign concept. The notion that a threading.Thread should always be (or at least be attempted to be) joined makes sense. The notion of categorically refusing to let a process end perhaps overreaches in certain situations.
I believe the more general solution exists in offering atexit handlers on multiprocessing.Process.
[](https://github.com/eryksun)
### eryksun commented on Jul 14, 2016
[](https://github.com/eryksun)
[eryksun](https://github.com/eryksun)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627189)
Contributor
More actions
> all atexit handlers, for example, would be called multiple times.
Davin is (I think) proposing a multiprocessing atexit facility, which can be used to ensure threading.\_shutdown is called. But could Python's regular atexit handling be reset in the child, allowing Py\_Finalize to be called? In other words, can atexit can be integrated into the PyOS\_AfterFork ([Modules/signalmodule.c](https://github.com/python/cpython/blob/main/Modules/signalmodule.c)) sequence? multiprocessing could set a sys flag that forces atexit to clear its registered handlers, and for Py\_AtExit, reset the static nexitfuncs variable in [Python/pylifecycle.c](https://github.com/python/cpython/blob/main/Python/pylifecycle.c). Or is that just opening a can of worms that will cause Py\_Finalize to crash in various scenarios?
> There's also the problem that fork() isn't MT-safe
This issue is about joining Python threads created in the child, which has a clean slate via PyOS\_AfterFork, PyEval\_ReInitThreads ([Python/ceval.c](https://github.com/python/cpython/blob/main/Python/ceval.c)), and threading.\_after\_fork.
[](https://github.com/bitdancer)
### bitdancer commented on Jul 14, 2016
[](https://github.com/bitdancer)
[bitdancer](https://github.com/bitdancer)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627190)
Member
More actions
As far as muliprocessing's "mentality" goes, it aims to provide the \*same\* API as Threading, so it is logical that it should preserve threading's behavior with respect to child threads in a process, rather than violating threading's model. Anything else is counter-intuitive to a python programmer, as demonstrated by this issue and Tim's comments :)
[](https://github.com/bitdancer)
### bitdancer commented on Jul 14, 2016
[](https://github.com/bitdancer)
[bitdancer](https://github.com/bitdancer)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627191)
Member
More actions
Note, however, that fixing this will be a backward compatibility issue, since there are doubtless programs relying on this behavior, probably mostly unintentionally.
[](https://github.com/tim-one)
### tim-one commented on Jul 14, 2016
[](https://github.com/tim-one)
[tim-one](https://github.com/tim-one)
[on Jul 14, 2016](https://github.com/python/cpython/issues/63166#issuecomment-1093627192)
Member
More actions
About: "The notion of categorically refusing to let a process end perhaps overreaches in certain situations." threading.py addressed that all along: if the programmer \_wants\_ the process to exit without waiting for a particular threading.Thread, that's fine, they ask the Thread constructor for a "daemon" thread. Whether a threading.Thread does or doesn't prevent process exit before it's .join()'ed has always been the programmer's choice. Python never attempted to guess their intent (except for "the main thread", which is necessarily non-daemonic). That's why it's especially surprising that multiprocessing can silently overrule what had always been an explicit choice about process-exit threading.Thread behavior.
About compatibility, yup, that's potentially painful. I will note that compability was already broken on Windows with no apparent angst, or subsequent complaints (the program in [bpo-27508](https://bugs.python.org/issue?@action=redirect&bpo=27508) is an example: "runs forever" under 3.5.2 but "ends very quickly" under 2.7.11; "runs forever" is what the programmer wanted, matching how they expected non-daemon threading.Threads to work).
[pitrou](https://github.com/pitrou)
added
[3\.7 (EOL)end of life](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%223.7%20\(EOL\)%22)end of life
[on Aug 16, 2017](https://github.com/python/cpython/issues/63166#event-6403189487)
[](https://github.com/pitrou)
### pitrou commented on Aug 16, 2017
[](https://github.com/pitrou)
[pitrou](https://github.com/pitrou)
[on Aug 16, 2017](https://github.com/python/cpython/issues/63166#issuecomment-1093627193)
Member
More actions
New changeset [ee84a60](https://github.com/python/cpython/commit/ee84a608587b930176d37303afae8a4358e15990) by Antoine Pitrou in branch 'master':
[bpo-18966](https://bugs.python.org/issue?@action=redirect&bpo=18966): non-daemonic threads created by a multiprocessing.Process should be joined on exit ([bpo-3111](https://bugs.python.org/issue?@action=redirect&bpo=3111))
[ee84a60](https://github.com/python/cpython/commit/ee84a608587b930176d37303afae8a4358e15990)
[](https://github.com/pitrou)
### pitrou commented on Aug 16, 2017
[](https://github.com/pitrou)
[pitrou](https://github.com/pitrou)
[on Aug 16, 2017](https://github.com/python/cpython/issues/63166#issuecomment-1093627194)
Member
More actions
This is now fixed in git master. Thank you for the report\!
[pitrou](https://github.com/pitrou)
closed this as [completed](https://github.com/python/cpython/issues?q=is%3Aissue%20state%3Aclosed%20archived%3Afalse%20reason%3Acompleted)
[on Aug 16, 2017](https://github.com/python/cpython/issues/63166#event-6403189488)
[ezio-melotti](https://github.com/ezio-melotti)
transferred this issue from
[on Apr 10, 2022](https://github.com/python/cpython/issues/63166#event-6403189489)
[Sign up for free](https://github.com/signup?return_to=https://github.com/python/cpython/issues/63166) **to join this conversation on GitHub.** Already have an account? [Sign in to comment](https://github.com/login?return_to=https://github.com/python/cpython/issues/63166)
## Metadata
## Metadata
### Assignees
No one assigned
### Labels
[3\.7 (EOL)end of life](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%223.7%20\(EOL\)%22)end of life[stdlibStandard Library Python modules in the Lib/ directory](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22stdlib%22)Standard Library Python modules in the Lib/ directory[type-featureA feature request or enhancement](https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-feature%22)A feature request or enhancement
### Projects
No projects
### Milestone
No milestone
### Relationships
None yet
### Development
Code with agent mode
Select code repository
No branches or pull requests
### Participants
[](https://github.com/applio)[](https://github.com/bitdancer)[](https://github.com/eryksun)[](https://github.com/pitrou)[](https://github.com/tim-one)
## Issue actions
## Footer
© 2025 GitHub, Inc.
### Footer navigation
- [Terms](https://docs.github.com/site-policy/github-terms/github-terms-of-service)
- [Privacy](https://docs.github.com/site-policy/privacy-policies/github-privacy-statement)
- [Security](https://github.com/security)
- [Status](https://www.githubstatus.com/)
- [Community](https://github.community/)
- [Docs](https://docs.github.com/)
- [Contact](https://support.github.com/?tags=dotcom-footer)
- Manage cookies
- Do not share my personal information
You can’t perform that action at this time.
Threads within multiprocessing Process terminate early · Issue \#63166 · python/cpython |
| Readable Markdown | null |
| Shard | 174 (laksa) |
| Root Hash | 6325672905007345774 |
| Unparsed URL | com,github!/python/cpython/issues/63166 s443 |