Spawning a child process

Spawning a child process

Post by William Robert Cav » Wed, 11 Jun 1997 04:00:00



This is a multi-part message in MIME format.

--------------5D093FD11470
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi..!

I am attempting to run a child process from my main Motif/X GUI program.
I want this to be non blocking ie I can return to the GUI to continue
work whilst the child process runs in the background. The child
process(es) are not X based programs but are just standard unix
executables using STDIN,STDOUT and FILES.

I want a dialogue to last for the duration of the program and then to
disappear after the process terminates. Indeed I have implemented a
progress bar utilising the Free Widget Foundation PcBar widget, such
that progress can be displayed.

So far, so good I've managed to implement this, however one problem
remains. I cannot kill the sub process using my GUI whilst using the
wait()/waitpid() functions. If I remove the wait() functions then I can
kill the sub process, however removing the wait from my signal handler
means that my child doesn't register a termination. In a nutshell i'm
using pipes and signal handlers to do this. Is this right?

I've attached the source code and a Makefile below showing my attempt at
just using a working dialog (ie without the added complexity of the
progress bar) to spawn a process from a simple (rowcol) pushbutton
interface, to illustrate my problem. If anyone could suggest
improvements,etc. for this process, particularly allowing me to use the
cancel button to kill the process, please let me know.

The program requires arguments of 1: subprocess executable name and 2:
the working directory.

eg. newshelp sarhp /users/wrc/
where sarhp is the executable to be run and /users/wrc/ is the working
directory.

Please note that full error checking is not included in this version to
reduce code size.

Many thanks.

William

--
Dr William Robert Cave
Proudman Oceanographic Laboratory
Bidston Observatory
Birkenhead
Merseyside
England
L43 7RA

--------------5D093FD11470
Content-Type: text/plain; charset=us-ascii; name="NewsHelp.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="NewsHelp.c"

#include <Xm/Xm.h>
#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <Xm/Label.h>
#include <Xm/MessageB.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

#define IN      1
#define OUT     0
#define MAX_BUFF_SIZE   150

typedef struct  {
                                        char *exename;
                                        char *workdir;
                                        char **argv;
                                        int argc;
                                        Pixel colour;
               pid_t pid;

}       PcBarData;

static int pcval;
static Widget PcBar;
int fd[2];

static void PcBarCB ( Widget, XtPointer,XtPointer);
static void QuitCB ( Widget, XtPointer,XtPointer);
static void PcBarOKCB(Widget,XtPointer,XtPointer);
static void KillChildCB(Widget,XtPointer,XtPointer);
static void (*orighandler)(int);
static void reaper(int);
static void ack_exit(XtPointer, int*, XtInputId*);
static void KillWidget(XtPointer,XtIntervalId *);
void ForceDialog(Widget);
void OSFCreateErrorDialog(Widget,char*,char *);
void CreateAndRunChildWorkingDialog(Widget ,PcBarData *);
static Widget CreateMWorkingDialog(Widget,char *,char *);

int main ( int argc, char **argv )
{
   Widget shell, rowcol,rbutton,qbutton;
   XtAppContext app;
   PcBarData pcbar;
   char *prgname=NULL,*workdir=NULL;
   char buff[MAX_BUFF_SIZE+1];  
   int i;

        if (argc >=2)
        {
                prgname = argv[1];
                if (argv[2]) workdir = argv[2];
      else workdir = getcwd(buff,MAX_BUFF_SIZE);
                pcbar.colour = 3L;
                if (argc==4) { sscanf(argv[3],"%d",&i);  pcbar.colour = (Pixel)i; }
        }
   else exit(EXIT_FAILURE);

   pcbar.exename = malloc( (strlen(prgname)+1)*sizeof(char) );
   strcpy(pcbar.exename,prgname);
   pcbar.workdir = malloc( (strlen(workdir)+1)*sizeof(char) );
   strcpy(pcbar.workdir,workdir);

    shell = XtAppInitialize ( &app, "Askquestion", NULL, 0,
                              &argc, argv, NULL, NULL, 0 );

    rowcol = XtCreateManagedWidget ("rowcol",xmRowColumnWidgetClass,shell,NULL,0);

    rbutton = XtCreateManagedWidget ( "Run program",
                                     xmPushButtonWidgetClass,
                                     rowcol, NULL, 0 );

    qbutton = XtCreateManagedWidget ( "Quit",
                                     xmPushButtonWidgetClass,
                                     rowcol, NULL, 0 );

    XtAddCallback(rbutton, XmNactivateCallback, PcBarCB, (XtPointer)&pcbar);                          
    XtAddCallback(qbutton, XmNactivateCallback, QuitCB,NULL);                          

    XtRealizeWidget ( shell );
    XtAppMainLoop ( app );
    return(0);

}

/************************************************************************/
/*
   Callback installs and executes the named child process.
*/
/************************************************************************/
static void PcBarCB ( Widget w,XtPointer clientData,XtPointer callData )
{
        PcBarData *pc=(PcBarData*)clientData;

   CreateAndRunChildWorkingDialog(w,pc);

}

/************************************************************************/
/*
   Callback terminates Motif Program.
*/
/************************************************************************/
static void QuitCB ( Widget w,XtPointer clientData,XtPointer callData )
{
   exit(EXIT_SUCCESS);

}

/******************************************************************/
/*
   Function creates a working dialog and runs the child program
   with data stored in PcBarData structure.
*/
/******************************************************************/
void CreateAndRunChildWorkingDialog(Widget w,PcBarData *pcbar)
{
        Widget dialog;
        int i,status;
        int result,cnt=0;
        pid_t pid;
        char line[51],c,errmsg[132];

        dialog = CreateMWorkingDialog(w,"UKOPMOD Sub Process",pcbar->exename);
   if (dialog)
   {
      XtManageChild ( dialog );
      ForceDialog(dialog);

        if (pipe(fd) < 0)
      {
         OSFCreateErrorDialog(w,"Sub Process Error","Duff  pipe formation");
         return;
      }

      orighandler = signal(SIGCHLD, reaper);
      XtAppAddInput(XtWidgetToApplicationContext(dialog),
                fd[OUT], (XtPointer)XtInputReadMask, ack_exit, dialog);

      if ( (pid = fork()) < 0)
      {
        OSFCreateErrorDialog(w,"Sub Process Error","Fork error");
         return;
      }
      else if (pid > 0)      /* PARENT code */
      {
        pcbar->pid = pid;
         XtAddCallback(dialog,XmNcancelCallback,KillChildCB,(XtPointer)pcbar);
         close(fd[IN]);         /* close parent write pipe */
         while (read(fd[OUT],&c,1) != NULL)
         {
                if ( (isalnum(c))||(c==' ')||(c=='=') )
            {
                                        line[cnt] = c;
                                        cnt++;
            }
            else cnt=0;
         }
      }
      else                      /* CHILD code */
      {
        close(fd[OUT]);         /* close childs read pipe */
         if (fd[IN] != STDOUT_FILENO)
         {
                if (dup2(fd[IN],STDOUT_FILENO) != STDOUT_FILENO)
            {
                OSFCreateErrorDialog(w,"Sub Process Error","Cannot duplicate STDOUT ");
               return;
            }
            close(fd[IN]);      /* Not needed after dup */
         }
         chdir(pcbar->workdir);      
         sprintf(errmsg,"Can't run sub-process: %s in directory %s",pcbar->exename,pcbar->workdir);
         if (execl(pcbar->exename,pcbar->exename,(char*)0) < 0) OSFCreateErrorDialog(w,"Sub Process Error",errmsg);
      }
   }

}

/*
   Create a working dialog that lasts for the process duration + 4seconds
*/
static Widget CreateMWorkingDialog(Widget w,char *name,char *process)
{
   Widget retw=NULL,form;
   char title[132];

   if (retw==NULL)
   {    
      sprintf(title,"%s running %s",name,process);
      retw = XmCreateWorkingDialog ( w, name, NULL, 0 );
      XtVaSetValues ( retw,
                                                XtVaTypedArg, XmNdialogTitle,XmRString,title,strlen(title)+1,
                     XtVaTypedArg, XmNmessageString, XmRString,title,strlen(title)+1,                                  
                     XmNwidth,400,
                     NULL );            
        }
        return(retw);

}

/**************************************************************************/
/*
   Destroy the calling widget
*/
/*************************************************************************/
static void PcBarOKCB(Widget w,XtPointer call,XtPointer client)
{
        if (w) XtDestroyWidget(w);      

}

/**************************************************************************/
/*
   Callback send a KILL signal to a child process
*/
/*************************************************************************/

static void KillChildCB(Widget w,XtPointer call,XtPointer client)
{
        PcBarData *pcbar=(PcBarData*)call;

   if (kill(pcbar->pid,SIGKILL)==0) fprintf(stderr,"Killed pid = %d\n",pcbar->pid);
   else fprintf(stderr,"KILL FAILURE on process %d\n",pcbar->pid);

}

/**************************************************************************/
/*
   None standard signal handler for child termination alert to motif
*/
/*************************************************************************/

static void reaper(int i)
{
    int stat;
    pid_t pid=0;

    pid = wait(&stat);
    write(fd[IN], "OK - Exited", 1);
    signal(SIGCHLD, orighandler);

}

/**************************************************************************/
/*
   Callback registered to destroy the Progress dialogue after termination
   of the child + 4 second delay
*/
/*************************************************************************/

static void ack_exit(XtPointer client_data, int *fid, XtInputId *id)
{
    Widget widget = *(Widget*)client_data;
    char buf[1024];

    read(fd[OUT], buf, sizeof(buf));
    close(fd[IN]); close(fd[OUT]);
    XtRemoveInput(*id);
    /* If not cancelled by the user destroy dialog after 4secs (4000ms) */
    XtAppAddTimeOut ( XtWidgetToApplicationContext ( widget ),  
                        4000,KillWidget,(XtPointer)widget );

}

...

read more »

 
 
 

Spawning a child process

Post by Cameron Hay » Fri, 13 Jun 1997 04:00:00



Quote:>I am attempting to run a child process from my main Motif/X GUI program.
>I want this to be non blocking ie I can return to the GUI to continue
>work whilst the child process runs in the background. The child
>process(es) are not X based programs but are just standard unix
>executables using STDIN,STDOUT and FILES.

[sample code deleted]

You probably want to close the connections to the X server in your child code
after the fork. I think this is in the FAQ as others probably will tell you.
But maybe this is not the cause of your problem.

--

Centre de recherche informatique de Montreal

 
 
 

1. Apache can't spawn child process

Help!

--

[Mon Aug 12 20:43:19 1996] access to
/usr/local/apache/cgi-bin/Count.cgi failed for nyct.net, reason:
couldn't spawn child process

How do I increase the amount of process so that there is enough for
cgi-bin access's?

I'm running Apache 1.1.1 on FreeBSD

TIA

- Paul

_______________________________
Paul James Justin Donnelly
Webmaster - New York Connect Ltd.


http://www.nyct.net
_______________________________
317 Madison Ave. Suite 907
New York City, NY 10017

Telephone #: 212-293-2620
Fax #:       212-293-2628
Modem #:     212-293-3703

2. How to read printer′s output FROM a serial line

3. cannot spawn child process

4. Apache + /etc/shadow

5. No such file or directory: couldn't spawn child process: e:/apache/htdocs/test.pl

6. va_list, va_start confusion

7. Can't spawn child process

8. Instaling Fireplug

9. Can't Spawn Child Process

10. Apache 1.3.3 - "Resource temporarily unavailable: couldn't spawn child process"

11. "couldn't spawn child process"

12. Apache cannot spawn child process

13. How to get PID of a child/spawned process?