| Monitor Debugger | Index Level | addbi (D3/Unix) |
| Syntax | |
| Category | Unix |
| Type | Definition |
| Description |
examines Unix signals in relationship to the Pick Virtual Machine.
This discussion is intended for experienced Unix programmers to interface Unix applications with Pick or to use Unix process synchronization in a purely Pick environment. For performance reasons, Unix signals are not used in regular Pick activity. They are used solely to handle exceptions. Diverting signal usage for an application would simply remove nonessential facilities, like the possibility to send a message or to logoff a process. This does not mean that signals can be used freely, though. The Pick Monitor provides a system call to process regular Pick signals inside a customized signal handler, thus combining system and application signal handling. The following list, details the Pick signal system call and gives some examples of application signal handler. Signal Usage The following is a table of the signals currently used by D3. Future development may require using more signals. D3 uses only Unix System V.3 signals, which are common to more recent Unix versions. Non Unix System V.3 signals are left to their default signal handler (normally SIG_IGN) as set by the system. Numerical values may vary between Unix implementations. It is very important to use the proper include when writing in C or the include dm,bp,unix.h, signal.h when writing FlashBASIC programs using signals. Signal Description SIGHUP Hangup. When received, the process is logged off Pick, but remains connected to the virtual machine. The signal is controlled by the hupcl command in the Pick configuration file. It is normally generated by the TTY device driver when data carrier is lost. This signal can be altered by the TCL command trap dcd command . SIGINT Interrupt. Generated by the BREAK key and the alternate Virtual Machine. The break character is defined by brkchr in the configuration file or by the TCL command set-break . The process is sent to the FlashBASIC, or system debugger, if brk-debug is on or a level is pushed if brk-level is on. SIGQUIT Quit. Generated by the ESC key or the alternate escape character as defined by the escchr in the configuration file or by the TCL command set-esc . A level is pushed if esc-level is on. If esc-data is on, a signal is still generated, but eventually ignored by the Virtual debugger. The character defined by set-esc will eventually be put in the process input buffer, but it must be emphasized that a noticeable delay can be experienced when inputting this character. SIGILL Illegal instruction. Sends the process to the system debugger with an 'illegal opcode' abort. Used for assembly single stepping on some implementations. SIGTRAP Trace trap. Sends the process to the system debugger with an 'illegal opcode' abort. Used for assembly single stepping on some implementations. SIGIOT I/O trap instruction. Sends the process to the system debugger with an 'illegal opcode' abort. SIGEMT Emulator trap. Sends the process to the system debugger with an 'illegal opcode' abort. Used for assembly single stepping on some implementations. SIGFPE Floating point exception. Sends the process to the system debugger with an 'illegal opcode' abort. SIGKILL Kill. This signal cannot be caught and will terminate the process immediately after doing a logoff. Killing the flusher of a virtual machine will log all processes off and shut down the virtual machine. SIGBUS Bus error. Sends the process to the system debugger with an 'illegal opcode' abort. Used for assembly single stepping on some implementations. SIGSEGV Segmentation violation. Sends the process to the system debugger with an 'illegal opcode' abort. Used for assembly single stepping on some implementations. SIGSYS Bad argument to a system call. Sends the process to the system debugger with an 'illegal opcode' abort. SIGPIPE Write to a pipe with no one to read it. The process is sent to the Virtual debugger. Pipes are sometimes used as 'tapes' to do file save. The other end of the pipe can be connected to a serial device, a communication server process... Therefore, when this signal is raised, the write system calls aborts. In an application environment, this signal should be caught and a message sent to the user saying 'Communication Server not Ready', for instance. The write system call would then be interrupted, reported to the save process as a 'parity' error, and the write would be retried until the write finally succeeds. SIGALRM Alarm clock. The default signal handler is a simple return. Therefore, the signal is active, but does nothing. It can be used in FlashBASIC, with the %alarm() function, do set time outs around critical sections. This signal can be altered by the TCL trap alrm command. SIGTERM Software termination signal. This signals terminates the Pick process, leaving it logged on, but disconnected. This signal 'freezes' the Pick environment. If the process is restarted, execution will resume where it stopped. Normally, this signal should be preceded by a SIGHUP to log the process off. SIGUSR1 User-defined signal 1. Not used. Can be used freely by the applications. SIGUSR2 User-defined signal 2. Force the process to examine its current state, possibly changing it. This signal is used for Pick message, by the TCL logoff , TCL , END commands. Sending this signal out of context will cause no harm. This should be the way, for instance, to wake up a process waiting in a %pause() system call. This signal can be used by applications, provided they call the Pick signal handler inside their customized signal handler. See the section about the examples below. SIGCLD Death of a child. Not used. SIGPWR Power fail. When received, the process is logged off Pick, but remains connected to the virtual machine. The behavior of the system depends on how the hardware generates this signal. If there is no battery back-up, it is unlikely that the virtual machine will be brought down gently. The system usually change its running state, which will control what happens. A ap - k command should be inserted in the appropriate shell script associated to the new run level. This signal can be altered by the TCL trap pwr command. Pick Signal System Call The Pick monitor provides a system call to inform the Pick Virtual environment of an incoming signal. This C function is normally called by the default signal system handlers, but it can be called by an application signal handler too. This function is defined as follows: #include "/usr/lib/pick/include/sigmon.h" void sigmon( code ) int code; code is the action code, as described in the following table. Note some functions do not return to the caller . Code Value/Description db_slcout 0/No operation. Simply forces the process to examine its current state. This function must be called by the SIGUSR2 signal handler. db_privop 7/Privileged opcode. Sends the caller to the system debugger. This call does not return to the caller. This call can be used to abort a C program, even if not called from a signal handler. db_break 10/Interrupt. Sends the process to the FlashBASIC, or system debugger. This function must be called by the SIGINT signal handler. Going to the system debugger is not immediate. Normally, the process will enter the debugger (or push a level) when the signal handler terminates. db_esc 12/Quit. Pushes a level . This function must be called by the SIGQUIT signal handler. Normally, the process will push a level when the signal handler terminates. db_logoff 14/Log off. This function is normally called by the SIGHUP handler. It can be called by other signal handlers as part of the application (like SIGALRM for instance, to log off a process after a given time). db_pwrdown -1/Disconnect. The process is disconnected from the virtual machine, but remains logged on. Examples This sections shows some simple examples of using signals in a Pick application, or cooperating with Unix applications. All these examples require writing a C signal handler, which must be linked with the Pick monitor, as detailed in this document. Time out The purpose is to write a signal handler which will log the user process off if there is no activity for a given time. It is assumed the user is in a FlashBASIC application, waiting input. - Write the following signal handler and function setalrm.c: #include <signal.h> #include "/usr/lib/pick/include/sigmon.h" myalrm(){ /* signal handler. When activated, log the process off */ sigmon( db_logoff ); } /* Set the new signal handler Set the signal handler to the application signal handler. Return the address of the previous signal handler, so that the basic application can remove the time out */ void (*setalrm())(){ return signal(SIGALRM, myalrm ); } < - Compile the previous program and incorporate it to the Pick monitor, by typing, in the dm account: addbi setalrm signal ar vru libgm.a setalrm.o make -f /usr/lib/pick/Makefile Note this incorporates the user-defined function setalrm() as well as the system call signal() not normally shipped with the Monitor. The latter will be extracted from the standard C library. The %setalrm function can then be called from FlashBASIC. - Enter the following 'application' program * * Reprogram the alarm handler, * keeping the previous system * handler * Note the function pointer * returned by the function * is treated as a pointer to a character. include dm,bp,unix.h signal.h old$alarm = (char*)%setalrm() * loop * Set the alarm to 10 minutes * From now on, if the user * doesn't enter a command before * 10 minutes, the process will * be logged off. %alarm(600) * .. display application entry screen here crt 'Command : ': input command while 1 do begin case case command = 'a' * ... put command 'a' routine case command = 'end' print 'end of the application' * disable the alarm and set the default alarm * handler back to the default. %alarm( 0 ) %signal( SIGALRM, (char*)old$alarm ) chain 'off' end case repeat Note that, in the example above, if the alarm was not disabled and if the signal handler is not reset to the default, the alarm clock would have continued to run, even if the process went back to TCL, thus logging it off later. A small FlashBASIC program, just rearming the alarm can be written to incorporate the alarm in PROCs or menus to achieve the same time out capability in TCL. Synchronizing Two Pick Processes On conventional Pick implementations, synchronizing two Pick processes is done either through polling for the existence of a file or, a little better, by using a FlashBASIC LOCK instruction. On most implementations, however, the FlashBASIC LOCK instruction itself involves, internally, a polling, thus making the waiting process to consume cpu resource. By using signals, it is possible to have a process waiting for a signal to occur (a BREAK, logoff or a signal generated by another process, possibly a Unix process or a Pick process from another Pick virtual machine) without any cpu consumption. The following example has one phantom task waiting for a signal sent by 'somebody' to go read a message in a pipe where the 'somebody' has deposited a message. This communication with message, probably, would be better achieved through Unix messages, but this is merely an example. Also, this is a one to one communication. Multiple partners in this scheme would require semaphores. The server process makes itself visible to the entire system (Pick and Unix) by writing a temporary file which contains its process id, which other processes use to send a signal to it. The (simple) signal handler uses SIGUSR1 . The 'message' is in ASCII, containing a header and some data. The message has the following format: +---+---+--------//-----------+ | |NL | + +---+---+--------//-----------+ | | | | | +- Data (code dependent) | +------------ New line (discarded) +---------------- Command code. T : Terminate M : Message R : file receive - Enter the following C signal handler: setusr1.c: #include <signal.h> #include "/usr/lib/pick/include/sigmon.h" myusr1(){ /* Just reset the signal for next time */ signal( SIGUSR1, myusr1 ); } /* Set the new signal handler Set the signal handler to the application signal handler. Return the address of the previous signal handler so that the basic application can remove the time out */ void (*setusr1())(){ return signal(SIGUSR1, myusr1 ); } - Enter the following phantom task code in the item dm,bp, pserver : pserver 001 ! 002 * Example of a file server running as 003 * a phantom 004 * Commands are received on a named pipe. 005 * 006 include dm,bp,unix.h signal.h 007 include dm,bp,unix.h mode.h 008 include dm,bp,unix.h fcntl.h 009 * 010 * Defines: 011 equ NL to char(10) ;* UNIX line terminator 012 equ AM to char(254) 013 equ PIPE to "/dev/mypipe" 014 equ BUFSIZE to 10000 ;* max message size 015 * 016 char buffer[BUFSIZE] 107 * 018 * Remove temporary file 019 execute '!rm -f /tmp/pserverid' 020 * 021 restart:* 022 * 023 * Open the communication pipe in read 024 * only, no wait on read 025 * If open error, stop, sending a 026 * message back to the originating 027 * process. 028 fd=%open(PIPE, O$RDONLY+O$NDELAY) 029 if fd<0 then 030 stop 1,"Cannot open '":PIPE:"'. Error ":system(0) 031 end 032 * 033 * Do not allow BREAK from now on 034 break off 035 * 036 * Create the temporary file which 037 * contains our pid, so that 038 * everybody on the system will 039 * know the server id 040 mypid=%pgetpid(-1) 041 execute "!echo ":mypid:" > /tmp/pserverid" 042 * 043 * Reprogram the alarm handler, 044 * keeping the previous system handler 045 * Note the function pointer returned 046 * by the function is treated as 047 * a pointer to a character. 048 old$usr1 = (char*)%setusr1() 049 * 050 * Go try read the pipe. If there is no 051 * message, the signal we received 052 * was not an application one. May be 053 * somebody tried to log us off 054 * so close the pipe, restore the 055 * signal and wait a bit. If we come 056 * come back, was a false alarm. Restart. 057 loop while 1 do 058 * Wait for a signal 059 %pause() 060 * 061 * Read the pipe 062 n=%read(fd, buffer, BUFSIZE ) 063 * 064 begin case 065 case n=-1 066 * IO error 067 gosub terminate 068 stop 1,"PSERVER: IO error ":system(0) 069 case n=0 070 * Pipe is empty... 071 * The signals we got is not 072 * the one we expected. Enable 073 * break to allow for a 074 * possible 075 * logoff, and restart 076 gosub terminate 077 sleep 1 078 goto restart 079 case 1 080 * Got something (n is the 081 * number of byte) 082 * The 1st byte is a code, 083 * the second a new line 084 * (discarded) 085 code=buffer[1,1] 086 message=buffer[3,n-2] 087 * Go handle the message 088 gosub do$it 089 end case 090 repeat 091 * 092 do$it:* 093 begin case 094 case code='T' 095 * Terminate 096 gosub terminate 097 stop 1,"PSERVER: Terminated" 098 case code='M' 099 * Message. 100 execute "msg * PSERVER: ":message 101 case code='R' 102 * Receive a file. The message is 103 * full filename (NL) item (NL) 104 * text 105 convert NL to AM in message 106 filename=message<1> 107 item=message<2> 108 message=delete(message,1) 109 message=delete(message,1) 110 open filename then 111 write message on item 112 close 113 end else 114 execute "msg !0 PSERVER: '":filename:"' is not filename" 115 end 116 end case 117 * 118 return 119 * 120 * Clean everything 121 terminate:* 122 %close(fd) 123 %signal( SIGUSR1, (char*)old$usr1 ) 124 execute '!rm -f /tmp/pserverid' 125 break on 126 return 127 * 128 end - Create a communication pipe by doing the following from TCL: su (must be superuser to do the following ) mknod /dev/mypipe p chmod 0666 /dev/mypipe exit (Get back to TCL) - Compile and catalog the FlashBASIC program, compile the C program and add it to the built in function list by: addbi setusr1 cc -c setusr1.c ar vru libgmu.a setusr1.o To be able to use the customized monitor with a phantom process, it is necessary to shutdown and to move the customized monitor to the common directory /usr/bin while being in single user mode. shutdown make -f /usr/lib/pick/Makefile init s (wait for the system to effectively go to single user) mv /usr/bin/ap /usr/bin/ap.save mv ./ap /usr/bin init 2 (go back to multiuser) Restart the Pick virtual machine. - Create the phantom task server: z pserver - The server is now waiting for a signal to read the message. Normally, this would be done by another process (Pick or Unix), but, just to test this, the following shell script allows sending messages, small Unix files or terminate the server: snd: # Send a command to pserver through a pipe PIPE=/dev/mypipe # the communication pipe SERVERID=/tmp/pserverid # where the server puts its PID COMMAND=$1 # Make sure the Pick server is active if [ ! -r $SERVERID ] then echo Pick server is not active exit 1 fi # Get the server pid PSERVERID=`cat $SERVERID` # Send it a signal 0 to test its existence kill -0 $PSERVERID if [ $? != 0 ] then echo Pick server is not active. PID is not valid. exit 1 fi # Parse command case $COMMAND in "r"|"R") # Receive a file : snd r unix.file # pick.file item echo "R\n$3\n$4\n~`cat $2~`" > $PIPE ;; "m"|"M") # Send a message: snd m <text> shift echo "M\n$*" > $PIPE ;; "t"|"T") # Terminate echo "T\n" > $PIPE ;; *) echo "usage: snd r unix.file pick.file item" echo " snd m message" echo " snd t" ;; esac # Wake up the server by sending SIGUSR1 # -30 for AIX; -16 for SCO, DG kill -30 $PSERVERID - Test the server by the following commands (from Shell): snd m Hi there This command should send a Pick message to all Pick users. snd r /etc/inittab dm,pointer-file, inittab This command should send the Unix file /etc/inittab into the Pick item dm,pointer-file, inittab . snd t This command should terminate the server process. |
| Options | |
| See Also | |
| Example | |
| Warnings | |
| Compatibility | D3/Unix |
| Monitor Debugger | Index Level | addbi (D3/Unix) |