Title: `multiprocessing.Process.is_alive()` can incorrectly return True after `join()` · Issue #130895 · python/cpython · GitHub
Open Graph Title: `multiprocessing.Process.is_alive()` can incorrectly return True after `join()` · Issue #130895 · python/cpython
X Title: `multiprocessing.Process.is_alive()` can incorrectly return True after `join()` · Issue #130895 · python/cpython
Description: Bug report Bug description: This came up in #130849 (comment) The problem is that popen_fork.Popen (and popen_spawn.Popen and popen_forkserver.Popen) are not thread-safe: cpython/Lib/multiprocessing/popen_fork.py Lines 25 to 35 in 02de9c...
Open Graph Description: Bug report Bug description: This came up in #130849 (comment) The problem is that popen_fork.Popen (and popen_spawn.Popen and popen_forkserver.Popen) are not thread-safe: cpython/Lib/multiprocessin...
X Description: Bug report Bug description: This came up in #130849 (comment) The problem is that popen_fork.Popen (and popen_spawn.Popen and popen_forkserver.Popen) are not thread-safe: cpython/Lib/multiprocessin...
Opengraph URL: https://github.com/python/cpython/issues/130895
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"`multiprocessing.Process.is_alive()` can incorrectly return True after `join()`","articleBody":"# Bug report\n\n### Bug description:\n\nThis came up in https://github.com/python/cpython/pull/130849#discussion_r1980137089\n\nThe problem is that `popen_fork.Popen` (and `popen_spawn.Popen` and `popen_forkserver.Popen`) are not thread-safe:\n\nhttps://github.com/python/cpython/blob/02de9cb9a8fa5b0ae3947231b8c0677834aaee45/Lib/multiprocessing/popen_fork.py#L25-L35\n\nThe first successful call to `os.waitpid()` may reap the pid so that subsequent calls raise an `OSError`. I've only seen this on macOS (not Linux). We may not yet however have set `self.returncode` -- that happens a few statements later, so `poll()` can return `None` if:\n\n1) The process has finished\n2) Another thread called poll(), but hasn't yet set `self.returncode`\n\nAnd then `is_alive()` can return True:\n\nhttps://github.com/python/cpython/blob/02de9cb9a8fa5b0ae3947231b8c0677834aaee45/Lib/multiprocessing/process.py#L153-L170\n\nNote that some classes like `concurrent.futures.ProcessPoolExecutor` use threads internally, so the user may not even know that threads are involved.\n\nRepro:\n\n\u003cdetails\u003e\n\u003csummary\u003erepro.py\u003c/summary\u003e\n\n```python\nimport os\nimport multiprocessing as mp\nimport threading\nimport time\nimport sys\n\noriginal_excepthook = threading.excepthook\n\ndef on_except(args):\n original_excepthook(args)\n os._exit(1)\n\nthreading.excepthook = on_except\n\ndef p1():\n pass\n\ndef thread1(p):\n while p.is_alive():\n time.sleep(0.00001)\n pass\n\ndef test():\n for i in range(1000):\n print(i)\n p = mp.Process(target=p1)\n p.start()\n\n t = threading.Thread(target=thread1, args=(p,))\n t.start()\n\n p.join()\n assert not p.is_alive()\n\n t.join()\n\ndef main():\n threads = [threading.Thread(target=test) for _ in range(10)]\n for t in threads:\n t.start()\n for t in threads:\n t.join()\n\nif __name__ == \"__main__\":\n main()\n```\n\u003c/details\u003e\n\n**NOTE**:\n* This is unrelated to free threading\n* `popen_fork.Popen` (and subclasses) are distinct from `subprocess.Popen`\n\n### CPython versions tested on:\n\nCPython main branch\n\n### Operating systems tested on:\n\nmacOS\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-131440\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/colesbury","@type":"Person","name":"colesbury"},"datePublished":"2025-03-05T21:09:49.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/130895/cpython/issues/130895"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:cc639176-42cd-f3c6-8045-5e34cfc4eb47 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | CD2E:64491:2620BBD:341CC1E:696AC9BD |
| html-safe-nonce | 621689d1e6dad551006d1ecd58c29912e320f0bd58f719843ec7bba87ac410f6 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDRDJFOjY0NDkxOjI2MjBCQkQ6MzQxQ0MxRTo2OTZBQzlCRCIsInZpc2l0b3JfaWQiOiIzODUwNjI5MTU4MzUzNDIyNzgxIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 1704a84869ffbed9a30a64b1feeb86405b8fb0b4fd5ebd1d79dbdd9ca6d78069 |
| hovercard-subject-tag | issue:2898511540 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/130895/issue_layout |
| twitter:image | https://opengraph.githubassets.com/74af25e31e3c2da2d471331cbeba0501329b61b793d12705fd106f03f30becb0/python/cpython/issues/130895 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/74af25e31e3c2da2d471331cbeba0501329b61b793d12705fd106f03f30becb0/python/cpython/issues/130895 |
| og:image:alt | Bug report Bug description: This came up in #130849 (comment) The problem is that popen_fork.Popen (and popen_spawn.Popen and popen_forkserver.Popen) are not thread-safe: cpython/Lib/multiprocessin... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | colesbury |
| hostname | github.com |
| expected-hostname | github.com |
| None | c785f4ce187e9e7331257791b36ddee01625bb8e292a9b4fe2c16d4c006abf5d |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | c718a376fcf780eb22089171adb84a543f660bf7 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width