[comp.unix.programmer] How to restore terminal after curses program crashes?

clegg@tolsun.oulu.fi (Matthew Tran Clegg/VTT) (02/13/91)

I've been working on a program that uses the curses package and
cbreak mode.  Once in a while, a bug will cause the program to
crash (for example, with a segmentation fault).  This completely
unhinges the terminal.  It won't respond to anything anymore,
except if I press ^C, then the csh prompt will be printed.

(I've noticed sometimes that nethack will crash in this way too, but
only when the game is better than any I've had in months -- a real bummer.)

Does anyone know how to restore the terminal to a sane state?
So far, the only thing that has worked for me is the power switch :-).

Matthew Clegg
clegg@tolsun.oulu.fi, February 13

pawel@cs.UAlberta.CA (Pawel Gburzynski) (02/14/91)

From article <1991Feb13.133332.22320@ousrvr.oulu.fi>, by clegg@tolsun.oulu.fi (Matthew Tran Clegg/VTT):
> I've been working on a program that uses the curses package and
> cbreak mode.  Once in a while, a bug will cause the program to
> crash (for example, with a segmentation fault).  This completely
> unhinges the terminal.  It won't respond to anything anymore,
> except if I press ^C, then the csh prompt will be printed.
> 
> (I've noticed sometimes that nethack will crash in this way too, but
> only when the game is better than any I've had in months -- a real bummer.)
> 
> Does anyone know how to restore the terminal to a sane state?
> So far, the only thing that has worked for me is the power switch :-).
> 
> Matthew Clegg
> clegg@tolsun.oulu.fi, February 13

How about 'tset ^j' (^j stands for control j). Generally, it is a bad habit
for a program using curses to crash without regaining control for resetting
the terminal.

				Pawel Gburzynski

Dan_Jacobson@ATT.COM (02/14/91)

> Once in a while, a bug will cause the program to crash (for example,
> with a segmentation fault).  This completely unhinges the terminal.

Most of the time I find the terminal will respond to "command^J", so I
my .profile I have:

if test -t
then
stty="eval
	stty sane;
	stty
	echo
	echok
	echoe
	ixany
	hupcl
	icanon
	icrnl
	-ocrnl
	onlcr
	-onocr
	erase ${erase_character-^?}
	intr ^G
	kill ^-
	eof ^D
	$stty_extra
"
#$erase_character: can set to ^H for those terminals where more convenient
#swtch '^Z' #^Z: datakit, swtch: not in Sun's 5bin/stty
#hupcl: then Oliver Lauman's screen(1) won't hang. sure, buddy.
export stty; $stty #now have handy $stty variable... if my terminal
#gets screwed up I just say $stty at the prompt


yup, I just say
$ $stty^J
and everthing is comfy again.

you're welcome.
-- 
Dan_Jacobson@ATT.COM  Naperville IL USA  +1 708-979-6364

jik@athena.mit.edu (Jonathan I. Kamens) (02/14/91)

   Your program should keep track of when curses is activated and when it
isn't.  It should then install signal handlers for all of the fatal signals,
and when it gets such a signal, restore the tty modes, remove the signal
handler, and send itself the signal again (to get a coredump, which you
presumably want for debugging).

  Actually, you shyould remove your signal handlers before calling the curses
function to restore the tty modes.  That way, if curses has somehow gotten
confused and manages to generate another signal while restoring the modes,
you'll get a coredump instead of an infinite loop.

  (Yes, I know it's considered bad form  to call complicated functions like
curses functions inside signal handlers.  But in this case, it's considerd
even worse form to leave the terminal in a screwed up state, so I think it's
worth trying.)

  As for recovering from screwed up terminal settings -- someone else
suggested using tset, and that will probably work; you can also try just
typing "reset," which should clear things up a little bit.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

mike (02/14/91)

In an article, clegg@tolsun.oulu.fi (Matthew Tran Clegg/VTT) writes:
>I've been working on a program that uses the curses package and
>cbreak mode.  Once in a while, a bug will cause the program to
>crash (for example, with a segmentation fault).  This completely
>unhinges the terminal.  It won't respond to anything anymore,
>except if I press ^C, then the csh prompt will be printed.

When your terminal is in a good mood, enter the following command:

	stty -g >$HOME/.stty

Then, put an alias in your $HOME/.profile (or whatever), such as:

	sane() stty `cat $HOME/.stty`

Obviously this is for the Bourne shell; translate as appropriate for
csh, or whatever you prefer to use. 

So, when nethack bites the dust, you enter:

	$ sane^J

This will restore your terminal exactly the way it was when you first
entered the 'stty -g' command.
-- 
Michael Stefanik                       | Opinions stated are not even my own.
Systems Engineer, Briareus Corporation | UUCP: ...!uunet!bria!mike
-------------------------------------------------------------------------------
technoignorami (tek'no-ig'no-ram`i) a group of individuals that are constantly
found to be saying things like "Well, it works on my DOS machine ..."

mark@intek01.uucp (Mark McWiggins) (02/15/91)

I have a little shell script named "j" in my bin directory: 

	stty sane
	stty intr 
	stty erase 

Then I just have to type 'j CTRL-J' and I'm back.

Hope this helps.
-- 
Mark McWiggins			Integration Technologies, Inc. (Intek)
+1 206 455 9935			DISCLAIMER:  I could be wrong ...
1400 112th Ave SE #202		Bellevue WA  98004
mark@intek.com    		Ask me about C++!

mjm@eleazar.dartmouth.edu (Andy Behrens) (02/15/91)

clegg@tolsun.oulu.fi (Matthew Tran Clegg/VTT) writes:
> I've been working on a program that uses the curses package and
> cbreak mode.  Once in a while, a bug will cause the program to
> crash (for example, with a segmentation fault).  
>
> Does anyone know how to restore the terminal to a sane state?
> So far, the only thing that has worked for me is the power switch :-).

The 'reset' command will do this.  However, since curses has probably
left your terminal in raw mode, carriage return is no longer considered
to be an end-of-line character -- you'll have to use a newline instead.

Typing

	ctrl-J reset ctrl-J

should fix everything.  If you've changed your kill characters, it will
be reset to a default value, so you might want to set it again with
'stty'.

Andy

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (02/16/91)

In article <436@bria> uunet!bria!mike writes:
> When your terminal is in a good mood, enter the following command:
> 	stty -g >$HOME/.stty

That's System V-specific, unfortunately.

A BSD solution is to run ``pty foo'' instead of ``foo'' so that whenever
foo exits (or stops) the tty modes will be restored properly with no
further effort on your part.

---Dan

roger@gtisqr.uucp (Roger Droz) (02/16/91)

In article <DANJ1.91Feb13170109@cbnewse.ATT.COM> Dan_Jacobson@ATT.COM writes:
>> Once in a while, a bug will cause the program to crash (for example,
>> with a segmentation fault).  This completely unhinges the terminal.
>
>Most of the time I find the terminal will respond to "command^J", so I
>my .profile I have:
>
>if test -t
>then
>stty="eval
>	stty sane;
>	stty
>	echo
     [ rest deleted ]

How about simply:
	stty="stty `stty -g`"

>yup, I just say
>$ $stty^J
>and everthing is comfy again.

I agree with jik@athena.mit.edu (Jonathan I. Kamens) that one should
write the signal handlers early on so that your curses programs die
gracefully.
____________
               Roger Droz       
()       ()    Maverick MICRoSystems / Global Technology International
 (_______)     Mukilteo, WA 
  (     )      
   |   |       Disclaimer: "We're all mavericks here: 
   |   |                    Each of us has our own opinions,
   (___)                    and the company has yet different ones!"

Internet: roger@mav.COM     UUCP: uw-beaver!gtisqr!roger

jpr@jpradley.jpr.com (Jean-Pierre Radley) (02/16/91)

In article <DANJ1.91Feb13170109@cbnewse.ATT.COM> Dan_Jacobson@ATT.COM writes:
>> Once in a while, a bug will cause the program to crash (for example,
>> with a segmentation fault).  This completely unhinges the terminal.
>
>Most of the time I find the terminal will respond to "command^J", so I
>my .profile I have:
>
>if test -t
>then
>stty="eval
>	stty sane;
>	stty
>	echo
>	echok
>	echoe
>	ixany
>	hupcl
>	icanon
>	icrnl
>	-ocrnl
>	onlcr
>	-onocr
>	erase ${erase_character-^?}
>	intr ^G
>	kill ^-
>	eof ^D
>	$stty_extra
>"
>yup, I just say
>$ $stty^J
>and everthing is comfy again.

I do about the same thing, but with somewhat less effort.

In .profile,
	STTY=`stty-g` export STTY

In .login,
	setenv STTY `stty-g`

Then, after a scrambled screen,
	$stty^J
restores my prior settings.


 Jean-Pierre Radley   NYC Public Unix   jpr@jpradley.jpr.com   CIS: 72160,1341

Dan_Jacobson@ATT.COM (02/16/91)

>>>>> On 16 Feb 91 03:23:19 GMT, jpr@jpradley.jpr.com (Jean-Pierre Radley) said:

J-P> In article <DANJ1.91Feb13170109@cbnewse.ATT.COM> Dan_Jacobson@ATT.COM writes:
>Most of the time I find the terminal will respond to "command^J", so I
>my .profile I have:
>
>if test -t
>then
>stty="eval
>	stty sane;
>	stty
>	echo
>	echok
>	echoe
>	ixany
>	hupcl
>	icanon
>	icrnl
>	-ocrnl
>	onlcr
>	-onocr
>	erase ${erase_character-^?}
>	intr ^G
>	kill ^-
>	eof ^D
>	$stty_extra
>"
>yup, I just say
>$ $stty^J
>and everthing is comfy again.

J-P> I do about the same thing, but with somewhat less effort.

J-P> In .profile,
J-P> 	STTY=`stty-g` export STTY

J-P> In .login,
J-P> 	setenv STTY `stty-g`

J-P> Then, after a scrambled screen,
J-P> 	$stty^J
J-P> restores my prior settings.

Yeah but, you omit any stty-ings you did before you captured them into
an environment variable---unless you're happy with the differing
defaults on different machines, e.g., "#"=erase.  Plus, stty -g, and
certainly stty-g, aren't portable.  Plus I invoke $stty in the
.profile too.

[Ego restored]
-- 
Dan_Jacobson@ATT.COM  Naperville IL USA  +1 708-979-6364

jerry@ora.com (Jerry Peek) (02/16/91)

In article <1991Feb14.192959.22939@dartvax.dartmouth.edu> andyb@coat.com (Andy Behrens) writes:
> clegg@tolsun.oulu.fi (Matthew Tran Clegg/VTT) writes:
> > I've been working on a program that uses the curses package and
> > cbreak mode.  Once in a while, a bug will cause the program to
> > crash (for example, with a segmentation fault).  
> 
> Typing
> 	ctrl-J reset ctrl-J
> should fix everything.

Once in a while I've had a session wedged bad enough that *each* character
I type is treated as a new command.  After this happened a few times,
I made the following symbolic link in my bin directory:

	ln -s /usr/ucb/reset ]

It makes a single-character command called "]" that does a "reset".
You should be able to use a single-character name for the other fixes
people have posted here, too.

--Jerry Peek, O'Reilly & Associates, Inc.   jerry@ora.com   +1 617 354-5800

mike (02/17/91)

In an article, gtisqr.uucp!roger (Roger Droz) writes:
>In article <DANJ1.91Feb13170109@cbnewse.ATT.COM> Dan_Jacobson@ATT.COM writes:
>
>How about simply:
>	stty="stty `stty -g`"
>

This won't work, because the ``stty -g'' will simply set the terminal to what
it was already set to.  You need to preserve the terminal state _prior_ to
it going insane.
-- 
Michael Stefanik, MGI Inc., Los Angeles| Opinions stated are not even my own.
Title of the week: Systems Engineer    | UUCP: ...!uunet!bria!mike
-------------------------------------------------------------------------------
Remember folks: If you can't flame MS-DOS, then what _can_ you flame?

art@pilikia.pegasus.com (Art Neilson) (02/17/91)

In article <1991Feb13.133332.22320@ousrvr.oulu.fi> clegg@tolsun.oulu.fi (Matthew Tran Clegg/VTT) writes:
>I've been working on a program that uses the curses package and
>cbreak mode.  Once in a while, a bug will cause the program to
>crash (for example, with a segmentation fault).  This completely
>unhinges the terminal.  It won't respond to anything anymore,
>except if I press ^C, then the csh prompt will be printed.
>
>(I've noticed sometimes that nethack will crash in this way too, but
>only when the game is better than any I've had in months -- a real bummer.)
>
>Does anyone know how to restore the terminal to a sane state?
>So far, the only thing that has worked for me is the power switch :-).

The best way to handle this is to trap signals in the C program which
uses curses and have the signal handler call endwin() prior to exiting.
-- 
Arthur W. Neilson III		| INET: art@pilikia.pegasus.com
Bank of Hawaii Tech Support	| UUCP: uunet!ucsd!nosc!pegasus!pilikia!art

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (02/17/91)

In article <449@bria> uunet!bria!mike writes:
> In an article, gtisqr.uucp!roger (Roger Droz) writes:
> >How about simply:
> >	stty="stty `stty -g`"
> This won't work, because the ``stty -g'' will simply set the terminal to what
> it was already set to.

Double-quotes force immediate ` and $ interpretation.

> You need to preserve the terminal state _prior_ to
> it going insane.

He is.

---Dan

babin@IRO.UMontreal.CA (Gilbert Babin) (02/18/91)

I have the same problem with AIX, but whenever I type a character (any one)
after the crash, the shell goes into an infinite loop.

Any ideas on how to solve that on AIX?

Gilbert
--
-----------------------------------------------------------------------
Gilbert Babin			Rensselaer Polytechnic Institute
babin@iro.umontreal.CA		Decision Sciences & Engineering Systems
(514)382-3863			Troy, NY, USA, 12180-3590

meissner@osf.org (Michael Meissner) (02/18/91)

In article <1991Feb17.164719.17328@IRO.UMontreal.CA>
babin@IRO.UMontreal.CA (Gilbert Babin) writes:

| I have the same problem with AIX, but whenever I type a character (any one)
| after the crash, the shell goes into an infinite loop.
| 
| Any ideas on how to solve that on AIX?

When debugging applications like the above, I typically invoke it via:

	nethack; reset_tty

where reset_tty is my shell script to reset all terminal modes to
normal values.  For most people, you can do:

	stty sane
	stty dec

(stty dec resets some things that sane does).  In case you are
curious, here is my reset_tty shell script (I have 3 environment
variables set in my .profile depending on what system I'm on --
ATT_STTY, OSF1_STTY, and BSD_STTY):

#! /bin/sh


if [ "$ATT_STTY" != "" ]; then
	stty			\
		erase	"^?"	\
		kill	"^u"	\
		intr	"^c"	\
		quit	"^\\"	\
		eof	"^d"	\
		eol	"^-"	\
		swtch	"^z"	\
		isig		\
		icanon		\
		istrip		\
		echoe		\
		echok		\
		ignbrk		\
		opost		\
		ixon		\
		ixoff		\
		-ixany		\
		-echonl		\
		-onlret		\
		-xcase

	if [ "${EMACS}" = "t" -o "${EMACS_KLUDGE}" = "t" ]; then
		stty -echo onlret
	fi

elif [ "$OSF1_STTY" != "" ]; then
	stty			\
		erase	"^?"	\
		kill	"^u"	\
		intr	"^c"	\
		quit	"^\\"	\
		eof	"^d"	\
		eol	"^-"	\
		rprnt	"^r"	\
		flush	"^o"	\
		werase	"^w"	\
		lnext	"^v"	\
		susp	"^z"	\
		dsusp	"^^"	\
		isig		\
		icanon		\
		istrip		\
		echoe		\
		echok		\
		ignbrk		\
		opost		\
		ixon		\
		ixoff		\
		-ixany		\
		-echonl		\
		-onlcr

	if [ "${EMACS}" = "t" -o "${EMACS_KLUDGE}" = "t" ]; then
		stty -echo onlcr
	fi
else
	stty	new
	stty	erase	"^?"	\
		kill	"^u"	\
		intr	"^c"	\
		quit	"^\\"	\
		start	"^q"	\
		stop	"^s"	\
		eof	"^d"	\
		rprnt	"^r"	\
		flush	"^o"	\
		werase	"^w"	\
		lnext	"^v"	\
		susp	"^z"	\
		dsusp	"^^"	\
		cooked		\
		cr0		\
		crtbs		\
		crterase	\
		crtkill		\
		ctlecho		\
		decctlq		\
		echo		\
		even		\
		ff0		\
		-lcase		\
		-litout		\
		-nl		\
		nl0		\
		-noflsh		\
		-nohang		\
		odd		\
		pass8		\
		-prterase	\
		-tabs		\
		tandem		\
		-tilde		\
		-tostop

	if [ "${EMACS}" = "t" -o "${EMACS_KLUDGE}" = "t" ]; then
		stty -echo nl
	fi
fi
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142

Considering the flames and intolerance, shouldn't USENET be spelled ABUSENET?

mike (02/18/91)

In an article, kramden.acf.nyu.edu!brnstnd (Dan Bernstein) writes:
|In article <449@bria> uunet!bria!mike writes:
|| In an article, gtisqr.uucp!roger (Roger Droz) writes:
|| |How about simply:
|| |	stty="stty `stty -g`"
|| This won't work, because the ``stty -g'' will simply set the terminal to what
|| it was already set to.
|
|Double-quotes force immediate ` and $ interpretation.
|
|| You need to preserve the terminal state _prior_ to
|| it going insane.
|
|He is.

True enough.  That's what I get for falling asleep at the wheel.
Sorry for any confusion.

Cheers,
-- 
Michael Stefanik, MGI Inc., Los Angeles| Opinions stated are not even my own.
Title of the week: Systems Engineer    | UUCP: ...!uunet!bria!mike
-------------------------------------------------------------------------------
Remember folks: If you can't flame MS-DOS, then what _can_ you flame?

bill@camco.Celestial.COM (Bill Campbell) (02/19/91)

In <1991Feb13.133332.22320@ousrvr.oulu.fi> clegg@tolsun.oulu.fi (Matthew Tran Clegg/VTT) writes:

>I've been working on a program that uses the curses package and
>cbreak mode.  Once in a while, a bug will cause the program to
>crash (for example, with a segmentation fault).  This completely
>unhinges the terminal.  It won't respond to anything anymore,
>except if I press ^C, then the csh prompt will be printed.

>(I've noticed sometimes that nethack will crash in this way too, but
>only when the game is better than any I've had in months -- a real bummer.)

>Does anyone know how to restore the terminal to a sane state?
>So far, the only thing that has worked for me is the power switch :-).

>Matthew Clegg
>clegg@tolsun.oulu.fi, February 13

I set an environment variable in my .login (.profile for /bin/sh
users)
	setenv NORMTTY			`stty -g`

This extracts the stty parameters in a form suitable as an
argument to stty so all I have to do is type:
	^Jstty $NORMTTY^J

where ^J is control-j.

This resets the terminal to your login state.

Bill
-- 
INTERNET:  bill@Celestial.COM   Bill Campbell; Celestial Software
UUCP:   ...!thebes!camco!bill   6641 East Mercer Way
             uunet!camco!bill   Mercer Island, WA 98040; (206) 947-5591

jpr@jpradley.jpr.com (Jean-Pierre Radley) (02/19/91)

In article <DANJ1.91Feb16002433@cbnewse.ATT.COM> Dan_Jacobson@ATT.COM writes:
>>>>>> On 16 Feb 91 03:23:19 GMT, jpr@jpradley.jpr.com (Jean-Pierre Radley) said:
>
>J-P> In article <DANJ1.91Feb13170109@cbnewse.ATT.COM> Dan_Jacobson@ATT.COM writes:
>
>J-P> I do about the same thing, but with somewhat less effort.
>
>J-P> In .profile,
>J-P> 	STTY=`stty-g` export STTY
>
>J-P> In .login,
>J-P> 	setenv STTY `stty-g`
>
>J-P> Then, after a scrambled screen,
>J-P> 	$stty^J
>J-P> restores my prior settings.
>
>Yeah but, you omit any stty-ings you did before you captured them into
>an environment variable---unless you're happy with the differing
>defaults on different machines, e.g., "#"=erase.  Plus, stty -g, and
>certainly stty-g, aren't portable.  Plus I invoke $stty in the
>.profile too.

Well, I thought one might have cleverly inferred, without my explicitly so
stating, that before I set my STTY environment value in my .profile or
.login, that _first_ I do all the specific settings for erase, intr, &c.,
that I desire.

 Jean-Pierre Radley   NYC Public Unix   jpr@jpradley.jpr.com   CIS: 72160,1341

greywolf@unisoft.UUCP (The Grey Wolf) (02/21/91)

[ Many people write about how to restore terminal settings... ]

I'm expecting a perl script from someone real soon :-).

Me?  Oh, my shell (a superset of {,t}csh) remembers the terminal modes at
the beginning of the session, or whenever one types "setty".  The shell has
code to catch SIGQUIT and restore the terminal modes.  This is most useful
when you haven't been thrown into raw mode -- you can just hit '^\' twice:
once to generate a core, and a second time to reset the terminal.  If you're
in raw mode, either "^Jreset^J" followed by a keyboard QUIT or "^Jrestty^J"
will return the terminal to its last saved state.

The really esoteric ones might want to make a Makefile to deal with it,
or write it in assembler, or ...
-- 
# The days of the computer priesthood are not over.
# May they never be.
# If it sounds selfish, consider how most companies stay in business.

allbery@NCoast.ORG (Brandon S. Allbery KB8JRR) (02/23/91)

As quoted from <MEISSNER.91Feb17170024@curley.osf.org> by meissner@osf.org (Michael Meissner):
+---------------
| In article <1991Feb17.164719.17328@IRO.UMontreal.CA>
| babin@IRO.UMontreal.CA (Gilbert Babin) writes:
| 
| | I have the same problem with AIX, but whenever I type a character (any one)
| | after the crash, the shell goes into an infinite loop.
| | 
| | Any ideas on how to solve that on AIX?
| 
| When debugging applications like the above, I typically invoke it via:
| 
| 	nethack; reset_tty
| 
| where reset_tty is my shell script to reset all terminal modes to
| normal values.  For most people, you can do:
+---------------

telotech[05]:128 K$ cat /usr/lbin/oops
:
# oops - run program and restore terminal
#

g=`stty -g`
"$@"
status=$?
stty $g
tput sgr0
blockon
if [ $status -ne 0 ]; then
    echo "oops: $1: exit $status" >&2
fi
telotech[05]:129 K$ cat pers/src/blockon.c
#include <fcntl.h>

main()
{
    return fcntl(0, O_SETFL, (fcntl(0, F_GETFL, 0) & ~O_NDELAY)) == -1;
}
telotech[05]:130 K$ _

I find this invaluable for debugging:  it restores the terminal after just
about anything (short of escape sequences that whack the terminal itself, i.e.
terminals that have escape sequences to change the baud rate).

Another trick I've used is to run a "script" variant I wrote which not only
restores the terminal afterward but logs the output.  (The main variation is
that you can specify any program as the "shell".)  That, however, doesn't
work on telotech because we don't have ptys (yet)....

++Brandon
-- 
Me: Brandon S. Allbery			    VHF/UHF: KB8JRR on 220, 2m, 440
Internet: allbery@NCoast.ORG		    Packet: KB8JRR @ WA8BXN
America OnLine: KB8JRR			    AMPR: KB8JRR.AmPR.ORG [44.70.4.88]
uunet!usenet.ins.cwru.edu!ncoast!allbery    Delphi: ALLBERY