DragonFly BSD
DragonFly submit List (threaded) for 2004-03
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: patch to make script(1) exit cleanly on reciept of signal


From: Matthew Dillon <dillon@xxxxxxxxxxxxxxxxxxxx>
Date: Sat, 27 Mar 2004 23:22:20 -0800 (PST)

:Subject says it all - patch is available here:
:
:http://catseye.webhop.net/DragonFlyBSD/patch/script.diff
:
:This basically means that, if you are running script(1) and you type
:'killall script' in another terminal, or otherwise kill the script
:process in a non-drastic way, the typescript file will be flushed, and
:the script program's controlling terminal will be reset to the usual
:non-raw state.
:
:I'm open to further suggestions on how to improve script(1)'s behaviour
:in these circumstances; in their absence I'll give it three days.
:
:-Chris

    Signal handlers are difficult to do right.  So, for example, what
    happens if the signal were to occur just *BEFORE* the select() ?
    The answer is: script would not exit at all.

    You could interlock the select, like this:

	volatile int sigcanexit;
	volatile int sigtermed;

	...


	sigcanexit = 1;
	n = select(master + 1, ...)
	sigcanexit = 0;
	if (sigtermed)
	    break;

	sighndl(int signo)
	{
	    sigtermed = signo;
	    if (sigcanexit)		/* safe to exit from signal handler */
		    exit(1);
	}

    Another option would be to make the timeval passed to select() a
    global and allow the signal handler to override it, so if the signal
    occurs just before the select() the select() will timeout quickly and
    fall through to the sigtermed exit case.

	volatile int sigtermd_interlock;
	volatile int sigtermed;
	volatile struct timeval globtv;

	...

	sigtermd_interlock = 1;
	if (flushtime) {
	    globtv.tv_sec = flushtime;
	    globtv.tv_usec = 0;
	} else {
	    globtv.tv_sec = 30 * 60;
	    globtv.tv_usec = 0;
	}
	sigtermd_interlock = 0;
	if (sigtermed)
		break;
	select (.... &globtv);
	if (sigtermed)
		break;

	...

	sighndl(int signo) 
	{
	    sigtermed = signo;
	    if (sigtermd_interlock == 0) {
		globtv.tv_sec = 0;
		globtv.tv_usec = 0;
	    }
	}

    Neither option is pretty but if I were to have to choose I would probably
    choose option #2.

					-Matt
					Matthew Dillon 
					<dillon@xxxxxxxxxxxxx>



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]