          <<< NOTED::DISK$NOTES7:[NOTES$LIBRARY_7OF4]HACKERS.NOTE;1 >>>
                               -< ** Hackers ** >-
================================================================================
Note 1786.0          how to force cleanup on image rundown?           20 replies
CUJO::SAMPSON                                       192 lines   2-NOV-1995 23:21
--------------------------------------------------------------------------------
	Hello,

	What do you think would be the best way to ensure that certain
cleanup tasks are *always* performed by a program on image rundown,
even if the user issues control-Y/STOP, or a QUIT to the debugger,
either of which prevents execution of the normal user-mode exit handlers?

	Use of the IMG$ADD_PRIVILEGED_VECTOR routine to specify a kernel
rundown routine has been suggested by a knowledgeable source.  Would it
be best to use this method to perform all critical cleanup in kernel
mode, or (alternatively) would it be possible to make use of this method
to force all declared user-mode exit handlers to execute (in user mode)?
How would/should the latter be done?

						Thanks,
						Bob Sampson


           <<< TURRIS::DISK$NOTES_PACK:[NOTES$LIBRARY]DEBUG.NOTE;4 >>>
                                   -< DEBUG >-
================================================================================
Note 1725.0              ensuring cleanup when debugging               4 replies
CUJO::SAMPSON                                        53 lines   1-NOV-1995 02:31
--------------------------------------------------------------------------------
	Hello,

	I've written a set of routines for a customer, and packaged them
as a shareable image.  Exit handlers are declared for cleanup at image
exit.  I try to ensure that the exit handlers get executed by preventing
anyone from deleting the process until after the exit handlers have
executed (the last one executed allows the process to be deleted again).

	The customer wants to link against this shareable image, and use
these routines, during application testing and debugging.  However, running
an application under the debugger allows all of the declared exit handlers
to be inadvertently skipped, if the user quits the debug session.  This
leaves the process undeletable and the cleanup undone.

	I'm looking for the best way to either ensure that all the exit
handlers run, regardless of whether the user quits the debug session,
or, failing that, to detect from within the routines at run time that
a debug session exists, and avoid making the process undeletable.

	There is a fairly simple way to determine whether the debugger
has already been invoked, shown below.

#include <ints.h>
#include <lib$routines.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>

uint32 debugger_activated()
{
  lib$establish(lib$sig_to_ret); /* return SS$_DEBUG if no debugger */
  lib$signal(SS$_DEBUG,1,"\002go"); /* try to invoke debugger */
  return SS$_NORMAL; /* if debugger was there */
}

main()
{
  if (debugger_activated() & 1)
    printf("The debugger has already been activated.\n");
  else
    printf("The debugger has *not* been activated yet.\n");
{

	This is enough to handle the usual case where the debugger is
initially given control, but it cannot handle the case where the application
starts without the debugger, the exit handlers are all declared, the process
is made undeletable, and then the user presses control-Y and issues the DEBUG
command.

	Does anyone know of a more foolproof way of doing the right thing?

							Thanks,
							Bob Sampson
================================================================================
Note 1725.1              ensuring cleanup when debugging                  1 of 4
SSPADE::DIETER                                       16 lines   1-NOV-1995 08:16
--------------------------------------------------------------------------------

you could setup a system wide DBG$INIT command 
procedure with the following contents:

define/command quit = "exit"

this would redefine the debugger's quit command
to be exit.  however, this might not work if some
users had their own dbg$init procedures...  I 
don't know offhand what happens if there is a 
job/process dbg$init logical AND a group/system
one, although I suspect the debugger will only
execute the 'local' one...  (you could have 
folks @ the system one from their local ones...)

Mary
================================================================================
Note 1725.2              ensuring cleanup when debugging                  2 of 4
CSC64::BLAYLOCK "If at first you doubt,doubt again." 33 lines   1-NOV-1995 13:32
--------------------------------------------------------------------------------


How do you deal with just a

	run image
	<ctrl/y>
	STOP

sequence?  This bypasses exit handlers also (with or without
the debuggers presence).

Anyway, if you are in kernel mode doing a 

	ctl$gl_pcb->pcb$v_nodelet = 1 ;

investigate the routine IMG$ADD_PRIVILEGED_VECTOR (on AXP it's
IMG$ADD_PRIVILEGED_VECTOR_ENTRY) to add a kernel rundown routine
to your image.  See [SYS.LIS]IMGMAPISD.LIS on a neighborhood results
listing.

For example:

static int kernel_rundown_routine( int ) ;

extern
	img$add_privileged_vector_entry( (*func)(), int, int ) ;

#define VEC_TYPE_KERNEL_RUNDOWN 2
#define PERM_FLAG_TEMPORARY 0

	...
	img$add_privileged_vector_entry(kernel_rundown_routine, 
			VEC_TYPE_KERNEL_RUNDOWN, PERM_FLAG_TEMPORARY );
================================================================================
Note 1725.3              ensuring cleanup when debugging                  3 of 4
CUJO::SAMPSON                                        40 lines   1-NOV-1995 21:47
                                -< cool ideas! >-
--------------------------------------------------------------------------------
	re .1:

	That's a good idea that I could incorporate into the routine that
checks for an active debug session; something like:

lib$signal(SS$_DEBUG,1,"\037define/command quit = \"exit\";go");


	re .2:

>How do you deal with just a
>
>	run image
>	<ctrl/y>
>	STOP
>
>sequence?  This bypasses exit handlers also
>(with or without the debuggers presence).

	Good point.  Clearly I hadn't dealt with that at all.

>investigate the routine IMG$ADD_PRIVILEGED_VECTOR (on AXP it's
>IMG$ADD_PRIVILEGED_VECTOR_ENTRY) to add a kernel rundown routine
>to your image.  See [SYS.LIS]IMGMAPISD.LIS on a neighborhood results
>listing.

	Ah, *very* intriguing, thanks!  This looks like the surest way
to see that the process is always made deletable after image rundown.

	Is there any way this could also be used to force all of the exit
handler linked lists (user, super, exec) to execute as well?  Are the
linked lists still intact when the kernel rundown routine runs?  Is there
a good way on both Alpha and VAX for the kernel rundown routine to execute
the exit handlers in the access modes (user, super, exec) from which they
were declared?

	The reason I ask is that, if I could ensure that the exit handlers
*always* execute, even when the process is stopped, then I might not even
have to ever make the process undeletable.  The rundown would *always*
get done, unless the system crashes, but at that point, who cares?!?
================================================================================
Note 1725.4              ensuring cleanup when debugging                  4 of 4
CSC64::BLAYLOCK "If at first you doubt,doubt again."  9 lines   2-NOV-1995 12:13
--------------------------------------------------------------------------------


I think that you might want to move this discussion to 
NOTED::HACKERS or to the VAXAXP::VMSNOTES conference.
There is a section in the IDSM on image rundown and
termination that would describe what lists are still
intact and at what time.  As to whether on not to execute
exit routines really depends on what you are trying to
clean up.
