gh-154751: Keep the screen alive in curses.initscr() after newterm() - #154752
Merged
serhiy-storchaka merged 5 commits intoJul 27, 2026
Conversation
…erm() When initscr() was called while a screen from newterm() was current, it returned a window created with no screen. The window therefore did not hold a reference to the screen it belonged to, so the screen could be collected while the window was still in use, and the next method call on the window read freed memory. It now passes the current screen, like newwin(), newpad() and getwin() already do. That is NULL for the screen created by initscr(), which has no screen object, so that case is unchanged.
serhiy-storchaka
self-requested a review
July 27, 2026 12:06
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Member
And this is right. Please add a test for this case. |
The test now checks the identity the review asked for. The NEWS entry goes away because set_term(), newterm() and this code path are all new in 3.16 and unreleased, so no user could observe the crash.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
curses.initscr()called while a screen fromcurses.newterm()was current returned awindow built with no screen. The window's
screenfield is the reference that keeps ascreen alive, so this window kept nothing alive. Dropping the screen freed its
WINDOW,and the next method call on the window read freed memory:
When the current screen came from
newterm(),initscr()now returns that screen's ownstandard window, so there is only ever one wrapper over that
WINDOWand it holds thescreen. Otherwise it passes
state->topscreen, matchingnewwin(),newpad()andgetwin(); that value is NULL for the screen created byinitscr(), which has no screenobject, so plain
initscr()use is unchanged.This restores what the screen objects documentation promises: "Each window keeps its screen
alive, so a screen remains valid as long as any of its windows does."
newterm()andset_term()are new in 3.16 (gh-90092, GH-151748), so no released versionis affected and there is no NEWS entry.
The reproducer above now prints
no crashand exits 0, andcurses.initscr() is screen.stdscris True where it was False. Tests: