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 */