Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Lib/test/test_curses.py
Original file line number Diff line number Diff line change
Expand Up @@ -3072,6 +3072,24 @@ def test_new_prescr(self):
del screen
gc_collect()

def test_initscr_after_newterm_keeps_screen_alive(self):
# initscr() called while a newterm() screen is current returns that
# screen's own standard window, so the window keeps the screen alive.
# It used to be a second wrapper created without a screen: using it
# after the screen was collected read freed memory, and both wrappers
# could delwin() the same window.
s1 = self.make_pty()
s2 = self.make_pty()
screen1 = curses.newterm('xterm', s1, s1)
screen2 = curses.newterm('xterm', s2, s2)
curses.set_term(screen1)
win = curses.initscr()
self.assertIs(win, screen1.stdscr)
curses.set_term(screen2)
del screen1
gc_collect()
win.addstr(0, 0, 'x')

@cpython_only
def test_disallow_instantiation(self):
# The screen type cannot be instantiated directly (bpo-43916).
Expand Down
18 changes: 17 additions & 1 deletion Modules/_cursesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6573,7 +6573,23 @@ _curses_initscr_impl(PyObject *module)
_curses_set_null_error(state, "wrefresh", "initscr");
return NULL;
}
PyObject *winobj = PyCursesWindow_New(state, stdscr, NULL, NULL, NULL);
if (state->topscreen != NULL) {
/* The current screen is one made by newterm(); return its own
standard window instead of a second wrapper over the same
WINDOW, which would delwin() it on its own. */
PyCursesScreenObject *so = (PyCursesScreenObject *)state->topscreen;
if (so->stdscr_win != NULL) {
if (curses_update_screen_encoding(so->stdscr_win) < 0) {
return NULL;
}
return Py_NewRef(so->stdscr_win);
}
}
/* Attach the current screen, like newwin(), newpad() and getwin() do,
Comment thread
fedonman marked this conversation as resolved.
so that the window keeps its screen alive. It is NULL for the
screen created by initscr(), which has no screen object. */
PyObject *winobj = PyCursesWindow_New(state, stdscr, NULL, NULL,
state->topscreen);
if (winobj == NULL) {
return NULL;
}
Expand Down
Loading