New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot call setupterm() more than once per process #33
Comments
The warning would be a good, inexpensive start. (Exception? But let's back up a sec. What's setupterm doing under the covers? It looks to me, from reading man pages, that it's setting up a bunch of per-process state by reading the terminfo DB into the process space (speaking very roughly). If it was simply blowing codes through a file descriptor, we could switch that from stdout and be on our mrery way, but I don't think that's all there is to it. I haven't been able to find a way to interact with terminfo from Python without going through |
Is this what you were looking at? http://bugs.python.org/issue7567 |
bug 7567 isn't specifically about this issue (cannot call initscr/endwin more than once w/o corruption), but the final comment by ferringb is:
|
"What's setupterm doing under the covers?" There is a global variable, "cur_term" in C-land, pointing to a TERMINAL structure of capabilities. This gets initialized by setupterm:
this is a global value you'll find all over libcurses, via term.h: ./base/lib_newterm.c:#include <term.h> /* clear_screen, cup & friends, cur_term / To properly use setupterm() for more than one definition, it is necessary to save and restore the value pointed to by (TERMINAL *) cur_term. Unfortunately, you won't find any mention, and therefor any visibility to the value of cur_term in Python's curses module (./Modules/_cursesmodule.c), so it is simply not possible to access this definition in any way, much less save/restore it. Refs: curses C code for setupterm -- ignore the if (reuse && ..) code, as reuse is explicitly set FALSE, at least in OBSD's impl.: http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libcurses/tinfo/lib_setup.c?rev=1.12 IBM AIX's manual page explicitly mentions the need to save/restore cur_term: http://pic.dhe.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.basetechref%2Fdoc%2Fbasetrf2%2Fsetupterm.htm |
for the test cases, it appears that correct test cases for different kinds of Terminals/calls to setupterm() can be achieved by using different test.py files for each, as each test file is run in a seperate process. Working on this now. Finding test cases that probably should not have succeeded, or have been evaluated in the way that they were, but were, simply because of this issue! |
closed by pull request #50 |
Whichever terminal "kind" was used when Terminal() was first instantiated will continue to be used for the remainder of the program, regardless of the value of "kind" argument to subsequent instantiations.
This is because of the curses C api that python hooks through, and some things done in setupterm() that last for the duration of the process.
The correct fix, would be that every time Terminal() is instantiated, a subprocess is spanwed, and termcap translation later requested is piped through it. This is the method that I use, by way that the first Terminal() instantiation occurs in sub-process, and not a thread. This may however be too bloated.
An intermediate fix that I would be happy to patch propose, would be to generate a warning -- if Terminal() is instantiated again, without the same "kind", then a warning is emitted.
$ python3 -c 'import blessings;print(repr(blessings.Terminal(kind="xterm").red_on_black));print(repr(blessings.Terminal(kind="vt220").red_on_black));'
'\x1b[31m\x1b[40m'
'\x1b[31m\x1b[40m'
$ python3 -c 'import blessings;print(repr(blessings.Terminal(kind="vt220").red_on_black));print(repr(blessings.Terminal(kind="xterm").red_on_black));'
''
''
The text was updated successfully, but these errors were encountered: