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).
_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,
+ 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;
}