[comp.sys.apollo] Apollo unkillable processes - One source.

anderson@atc.sps.mot.com (howard anderson) (09/21/90)

This is a followup to my earlier request for help.  Since that
time we have discovered what appears to be the source of the problem.
The Apollo routine prf_$queue_file which queues a file to the printer
changes the task structure of the calling program permanently and
appears to reroute signal handling in some manner involving RPC.
Under certain conditions, quit and stop signals seem to be no longer
handled as before and the program can be rendered unkillable.
It is unknown whether other Apollo procedure calls also modify the
task structure of the calling program.  It is something to ponder.

The program below illustrates this condition.  You must have a 
release 10.2 printer up and running and change the printer name
and site id in the program below to see the effect.  If your
printer is not running and the job cannot be queued, the effect
does not occur.  The program below queues and prints a one-line
file.  There certainly could be something wrong with the program 
below so I'm definitely not making any strong claims.   I merely
claim that the behavior is most unexpected.

The program below can be exited of course.  An unkillable process
could result when a child is forked, pipes are opened, the child is
killed and there is no way left to send a carriage return to the
parent?  (kill -9 does not work either by the way).

It is possible that there is a use for unkillable processes so
perhaps we should try to make use of this effect.  Some sort
of security watchdog program perhaps.   

I apologize in advance for the length of this transmission but
I hope it will prevent someone else from having to figure this out.

I welcome any comments.  


/*******************************************************/
/* Unkillable process demonstration by Tom Krehbiel    */
/* with modifications by Howard C. Anderson.           */
/* This requires a release 10.2 printer named "howard" */
/* running on node "//howard".   (Or change the        */ 
/* source code as indicated.)                          */
/*                                                     */
/*******************************************************/
/*
The following is a shell script to compile and bind 
the program (test.c) that follows immediately:

#!/com/sh
eon
abtsev -m
von

cc test.c -dba

bind <<!
test.bin
-inlib /lib/prflib 
-b test
!

*/

/* Start of program "test.c" */                                         
                            
#include <stdio.h>                                                             
#include <sys/wait.h>
#include <ctype.h>
#include "/sys/ins/base.ins.c"
#include "/sys/ins/name.ins.c"
#include "/sys/ins/pgm.ins.c"
#include "/sys/ins/sio.ins.c"
#include "/sys/ins/error.ins.c" 
#include "/sys/ins/prf.ins.c"

status_$t      st;

static void check()
{
    if(st.all != status_$ok){
      error_$print(st);
    }
}

main( argc, argv, envp )
int  argc;
char *argv[], *envp[];
{
    char str[80];
    FILE *fopen(),*fp; 
    name_$pname_t queue_name;
    short queue_len;
    char filename[256];
    char printer_name[256];
    char printer_site[256];
                                     
/*******************************************************************/
    strcpy(printer_name,"howard");    /* Change this to the name of a
REL 10.2 printer at your site      */
    strcpy(printer_site,"//howard");  /* Change this to a printer site
name appropriate for your site    */
                                      /* Your printer must be up and
running to demonstrate this effect. */
                                     
/*******************************************************************/
    strcpy(filename,"test.file");
                    
    fp = fopen(filename,"w");
    fprintf(fp,"This is a test file that will be printed.\n");
    fclose(fp);

    printf("\nIn another window, pst -un to find process id of this
process (test).\n");
    printf("tb -t this process and note that no RPC stuff is present.  \n");
    printf("\nAfter traceback is complete, press return:  ");

    gets(str); /* Wait for carriage return. */
                                                                 
    /* Prf_$init() sets the print request packet options to their
default values. */
    prf_$init(ios_$errout,st);                                         
    check();
                                
    /* Set the PR[INTER] option  */
    prf_$set_option( "PR", (short)2, 0, printer_name,
(short)strlen(printer_name), true, st);
    check();

    /* Set the S[ITE] option  */
    prf_$set_option( "SITE", (short)4, 0, printer_site,
(short)strlen(printer_site), true, st);
    check();

    /* Write a print request packet to SITE/sys/print/queue */

    /****** THIS NEXT STATEMENT IS THE SOURCE OF THE RPC TAKEOVER OF
THIS PROCESS ********/
    prf_$queue_file( *filename, (short)strlen(filename), queue_name,
&queue_len, st);
    check();

   
printf("\n--------------------------------------------------------------
----\n");
    printf("\n\ntb -t this process again now and note that RPC stuff has\n");
    printf("been injected into this process.  After traceback is
complete, \n");
    printf("CTRL-Q this process.  You will see it hang.\n");
    printf("\nThen sigp -q this process.  You will see that it still
hangs.\n");
    printf("\nThen sigp -s this process.  You will see that it still
hangs.\n");
    printf("\nThen issue a carriage return to this process in its input
pad.\n");
    printf("The process then exits.  Unfortunately in our actual
application,\n");
    printf("whatever action is required cannot be accomplished.  This
program\n");
    printf("merely illustrates the general nature of the problem.\n");
    printf("\nThe source of this interlock problem is the prf_$queue_file\n");
    printf("statement which injects RPC stuff into our process.\n");
    printf("\nThis problem does not occur if no prf_$queue_file
statements are used.\n");
    printf("\nThis problem does not occur when a release 9.7 printer is
used.\n");
    printf("(You have to set the -pre10 option and have a valid printer
name set.)\n");

    gets(str); /* Wait for carriage return. */
}  
/* end of program test.c */