3

我正在调查curses.wrapper无法正确恢复终端的错误。该问题在背景/前景序列之后显示。

考虑以下保存在中的 python 程序myprogram.py

import curses, subprocess

# Function that does nothing
def f(*args, **kwargs):
    pass

curses.wrapper(f)

# Call vi to open a file 
subprocess.call("vi /tmp/foo", shell=True)

重现问题的步骤:

  1. 运行程序:python myprogram.py
  2. 它开始 vi 编辑文件/tmp/foo
  3. 当我击中ctrl-z它时,它让我回到我的壳里
  4. 当我恢复程序时fg
  5. 它重新启动编辑器但屏幕错误(全黑且未绘制编辑器)

删除curses.wrapper(f)线使程序工作:当程序恢复时,编辑器被正确绘制。

我尝试了多种方法,例如将调用替换为curses.wrapper(f)实际执行的操作,并且最小的示例(即调用initscr, endwin)也会导致相同的问题。

我在跑步:

  • zsh 5.0.5,我也试过了最新的fish shell版本
  • 蟒蛇2.7.6
  • VIM - Vi 改进版 7.3

我错过了什么?

4

2 回答 2

3

curses.wrapper的源代码对信号没有什么特别的作用。

在初始化期间(例如调用initscr),ncurses 库为这些信号添加处理程序:SIGINTSIGTERMSIGTSTPSIGWINCH。无论出于何种原因(可能是因为它是调用者无法直接看到的内部细节),这主要记录在NEWS文件中。

需要添加自己的信号处理程序的应用程序应该在 ncurses 初始化之后执行此操作(因为 ncurses 仅执行一次)。因为 curses 应用程序可以切换到屏幕模式/从屏幕模式切换,所以信号处理程序保持活动状态,直到程序退出。例如,Python 脚本curses.wrapper可能会多次调用(尽管它可能无法正常工作,除非使用 ncurses —— X/Open 说“可移植应用程序不能多次调用initscr )。

按照@lc2817的建议保存和恢复信号处理程序状态是可行的——但它一种解决方法,因为它并不优雅。如果curses.wrapper修改为向它添加一些状态,以记住它之前是否被调用过,并保存/恢复信号处理程序,那么解决方法将是不必要的。为了使它真正可移植,initscr应该在第一次使用时调用,并refresh在后续使用时调用。

于 2015-07-15T21:44:33.947 回答
3

这恰好是一个错误curses.wrapper或下面的任何东西,忘记将信号处理程序恢复到以前的值。这修复了它:

import curses, subprocess
import signal

# Function that does nothing
def f(*args, **kwargs):
    pass

a = signal.getsignal(signal.SIGTSTP)

curses.wrapper(f)

signal.signal(signal.SIGTSTP, a)

# Call vi to open a file 
subprocess.call("vi /tmp/oo", shell=True)
于 2015-07-15T20:46:59.210 回答