[comp.sys.apollo] Need help with unix fork function

clif@ticipa.ti.com (Clif Harden) (11/16/89)

In porting some unix software to our apollo system I have run
into a problem using the unix fork function on our apollos.

The node I am using is a DN3500, SR10.1,  running Aegis, bsd4.3,
and sys5.3.  It has all the known needed patches installed.

I have included a small test program that can be used to 
demonstrate the problem.  I don't recommend that you run
this program as the problem(s) caused can be very nasty.

The program scenario is this.  I start the program in a pad, the 
program then opens a new frame on the pad and clears it.  The 
program then displays a list of numbers and waits for keyboard 
input.  If a "q" key is pressed the program terminates properly 
with no problems.  If a "e" key is pressed the program will
execute a function that will fork a very simple child process.
The child process executes properly and terminates.  This is when
things go belly up big time.  

When the child process terminates it clears the frame and causes all
further messages to be displayed at the bottom of the screen.  
I can tell the parent process is still running because when I press
the "q" key the input transcript pad returns to the bottom of the
screen, but the parent process never totally terminates, you will
never get the pad back into the DM mode.  The only way to get rid of
the process is to log out and blast processes.  In some cases I have
had it totally lock up a node to the point I had to press the reset
switch.  

I think I know what is going on.  Since the parent process and child
process are duplicates I think they are sharing some task and display
system pointers.  When the child process terminates the pointers are
changed or deleted leaving the parent process in limbo or worse with
wrong pointers.
                       
In my discussions with the Apollo hot line about porting this 
software they recommend running this program in a VT100 emulator.
However due to the sorry state of Apollo's VT100 emulator that is
not possible, it causes more problems than it fixes and it destroys
the usefullness of the program.  The hot line on this problem has
been of little help. 

My opinion is a UNIX program should be able to use the DM pads in
any mode, not just with a VT100 emulator. 

Any help with this problem would be appreciated.  Help from the 
Apollo/Hp personel who read this news group would be especially
appreciated.

The following is the example program.

***************** Start of program **************************

/*
**  Name of Program -- fork_test
**
*/

#nolist
#include <apollo/base.h>
#include <apollo/cal.h>
#include <apollo/error.h>
#include <apollo/ios.h>
#include <apollo/pad.h>
#include <apollo/pgm.h>
#include <apollo/time.h>
#include <stdio.h>  
#list

#define DISPLAY_UNIT    ((short)1)

static void
check_status(status_$t status)
{
long count;

    if (status_$ok != status.all)   {
        error_$print(status);
        for( count = 0; count <100000000; count++);  
        pgm_$exit();
    }
}

execute(command,arg1,arg2,arg3,arg4)
char *command,*arg1,*arg2,*arg3,*arg4;
{
int fderr,cpid,wait_stat;
long err_pos,count;

printf("Starting to do the fork\n\n");
for(count=0;count<1000000;count++);
if ((cpid = fork()) == 0)
  if (execlp(command,command,arg1,arg2,arg3,arg4,NULL))
      {
      printf("Cannot execute %s\n",command);
      return;
      }            
while (wait(&wait_stat) != cpid);

printf("Exiting the excute routine\n\n");
for(count=0;count<1000000;count++);

return(0);      
}

int
main(void)
{
    pad_$window_list_t  window_list, window_2list;
    pad_$window_desc_t  window_one, window_two;

    ios_$id_t           stream_one, stream_two, stream_three;
    ios_$id_t           pane_stream;
    stream_$sk_t        frame_seek_one;
    status_$t           status;

    short               window_no1, window_no2, window_no3, status_code;
    long                buf_size, count;
    short               pane_count;
    char                buffer[1000],in_buffer[1000],stop,b;
    int                 a;   
    char                *data_string;
	
    /*  Set the original positions of the number 1 window.  */

    window_one.top = 0;
    window_one.left = 50;
    window_one.width = 1100;
    window_one.height = 750;

    /*  Set the original positions of the number 2 window.  */

    window_two.top = 0;
    window_two.left = 0;
    window_two.width = 40;
    window_two.height = 750;

     /*  Create frame on a pad  */

     pad_$create_frame( ios_$stdout,
                     (short)1,
                     (short)25,
                     &status );
    check_status(status);               

    /*  Get value of window_no1 for next calls.   */

    pad_$inq_windows(   ios_$stdout,    /*  Stream id                   */
                        window_list,    /*  Location, size of window    */
                        (short)0,       /*  No need for position info   */
                        &window_no1,    /*  Returns no of windows       */
                        &status );      /*  Status code                 */

    check_status(status);
    pad_$raw( ios_$stdout,&status ); 

    data_string = "1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n";
    buffer[0] = 0;
    strcat( buffer,data_string);
    data_string = "15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n";
    strcat( buffer,data_string);
    buf_size = strlen(buffer);

    ios_$put( ios_$stdout,
              ios_$cond_opt,
              buffer,
              buf_size,
              &status );    
    check_status(status); 

    stop = 0;

    printf("Ready for keyboard input\n\n");

    do {
       
         a = getchar();   
          switch (a) { 
                 case 81 :                 /* q or Q key */ 
                 case 113 : stop = 1;
                           break;
                 
                 case 69 :                 /* e or E key */
                 case 101 : execute("/bin/chmod","645","//gollum/local/clif/c/s/tpath",NULL); 
                           break;

                 default : printf(" %d ",a);
                           stop = 0;
                           break;
                     }

       } while( stop == 0 );
    
    pad_$cooked( ios_$stdout,&status );
    frame_seek_one.offset = NULL;

    pad_$clear_frame( ios_$stdout,
                      frame_seek_one,
                      &status);            
     
    /*  Close streams before terminating program.   */
    
    pad_$delete_frame( ios_$stdout,
                       &status);             

    ios_$close(stream_two, &status);  
    check_status(status);

}                                                            

***************** End of program ****************************
                                
Have a nice day!!

Clif Harden                    TI PAC Apollo Network Adminstrator
Texas Instruments              ARPA: clif@ticipa.ti.com 
PO Box 655012  M/S 3635        
Dallas, TX 75265