[Pinfo-devel] [PATCH] handle terminal stop/continue properly

Scott Mcdermott scott at omnisys.com
Wed Sep 8 22:36:46 UTC 2010


Hello,

Pinfo has a bug where it can't be used after being
continued from job stop in the shell (i.e.  control-z).
It will eat a CPU after resume, endlessly doing main
keypress handling loop because every time it calls
curses getch() after suspend, it will get ERR, until
curses has been "reset." The terminal needs to be
handed back to the calling program (i.e. bash) for
suspend, and then refreshed on resume.

I am surprised this bug went so long unfixed, because
using multiple jobs in a shell seems like a common
activity.

I debugged this and made the following patch, which
works well for me.

Please apply.  Thanks.


Index: src/utils.c
===================================================================
--- src/utils.c	(revision 308)
+++ src/utils.c	(working copy)
@@ -376,10 +376,15 @@
 void
 waitforgetch()
 {
+	int ret;
+
 	fd_set rdfs;
 	FD_ZERO(&rdfs);
 	FD_SET(0, &rdfs);
-	select(1, &rdfs, NULL, NULL, NULL);
+
+	/* we might get interrupted by e.g. SIGTSTP/SIGCONT */
+	do ret = select(1, &rdfs, NULL, NULL, NULL);
+	while (ret == -1 && errno == EINTR);
 }
 
 /* returns 0 on success, 1 on error */
Index: src/signal_handler.c
===================================================================
--- src/signal_handler.c	(revision 308)
+++ src/signal_handler.c	(working copy)
@@ -44,6 +44,29 @@
 }
 
 void
+handle_suspend(int signum)
+{
+	if (!isendwin()) {
+		curs_set(1);
+		endwin();
+	}
+	fprintf(stderr, "\n");
+	signal(SIGTSTP, handle_suspend);
+	kill(0, SIGSTOP);
+}
+
+void
+handle_resume(int signum)
+{
+	if (isendwin()) {
+		refresh();
+		curs_set(0);
+	}
+	ungetch(keys.refresh_1);
+	signal(SIGCONT, handle_resume);
+}
+
+void
 signal_handler()
 {
 	sigset_t sigs;
@@ -52,6 +75,8 @@
 	signal(SIGTERM, handle_crash);	/* handle soft kill */
 	signal(SIGSEGV, handle_crash);	/* handle seg. fault */
 	signal(SIGHUP, handle_crash);	/* handle hup signal */
+	signal(SIGTSTP, handle_suspend);/* handle terminal suspend */
+	signal(SIGCONT, handle_resume);	/* handle back from suspend */
 #ifdef SIGWINCH
 	signal(SIGWINCH, handle_window_resize);
 #endif
Index: src/manual.c
===================================================================
--- src/manual.c	(revision 308)
+++ src/manual.c	(working copy)
@@ -967,7 +967,7 @@
 			key = pinfo_getch();
 		}
 		/************************ keyboard handling **********************************/
-		if (key != 0)
+		if (key > 0)
 		{
 			if ((key == keys.print_1) ||
 					(key == keys.print_2))



More information about the Pinfo-devel mailing list