I have a CProgramA that need to call CProgramB just before CProgramA terminates. How can this be achieved?

Recommended Answers

All 30 Replies

Do you want CProgramA to stay around to wait for CProgramB to finish?

Which OS/Compiler are you using?

@jobs
If you just want to start a process CreteProcess or CreateProcessAsUser can help you on Windows. CreateProcessAsUser documentation has one example as well.
However, I am sure you can complicate this question up to a great extent.

>However, I am sure you can complicate this question up to a great extent.
Yea, like "oh wait, I'm not using Windows!". ;)

Yea, like "oh wait, I'm not using Windows!".

No offence. Concern still remains the same !!

>Concern still remains the same !!
What concern? Salem already asking what OS and compiler the OP is using, information that is critical for answering the question. All you did was guess, and that's not really helpful.

>>All you did was guess, and that's not really helpful.

Of course it was a guess but I am not sure if it was not useful.
I was just trying to give pointers. I pity if you think it is a bad idea ?

Do you want CProgramA to stay around to wait for CProgramB to finish?

Which OS/Compiler are you using?

I am using Linux Fedora, gcc 4.1.2-14.

My problem is, ProgramA starts and don't know how long and when it will finish executing. But ProgramB depends on the file ProgramA creates. Easy way to do this is have ProgramA call ProgramB before ProgramA terminates. I would prefer to have ProgramA kick off ProgramB and terminate than have ProgramA hang around while only ProgramB is doing some work.

If there is no need for A to wait for the result, you may as well use the exec() functions, like say execl().

If there is no need for A to wait for the result, you may as well use the exec() functions, like say execl().

What if you want A to wait until B completes?

> What if you want A to wait until B completes?
Then A calls fork() to create a child process, and the child calls execl().
The parent then calls wait(), to wait (obviously) for the child to finish.

pid = fork();
    if ( pid < 0 )
    		 { 
    			syslog(LOG_ERR,"Cannot fork!!");
    			exit(1);
    		 }
    if ( pid == 0 )
    	{ /* Child process */

    	 execl("./myprogB",0);
    	}
    
    while (wait(&status) != pid)
            /* empty */ ;

for whatever reason, forked program doesn't seem to finish or stuck some where. When I run them independently, they run fine. I log to syslog from both cprograms. If I fork it, then I can't syslog to it as a independent cprogram (as a different process) or would it be possible that syslog sees parent/child as same, not two different process?

You don't check that execl() doesn't return. If it does, there has been an error, and there is NO exec'ed process.

You don't check that wait() doesn't return an error. If it does, your code will loop forever.

"This ain't like dusting crops boy", you need to check everything all the time, not when someone nags you into doing it.

pid = fork();
    if ( pid < 0 )
    		 { 
    			syslog(LOG_ERR,"Cannot fork!!");
    			exit(1);
    		 }
    if ( pid == 0 )
    	{ /* Child process */

    	 execl("./myprogB",0);
    	}
    
    while (wait(&status) != pid)
            /* empty */ ;

for whatever reason, forked program doesn't seem to finish or stuck some where. When I run them independently, they run fine. I log to syslog from both cprograms. If I fork it, then I can't syslog to it as a independent cprogram (as a different process) or would it be possible that syslog sees parent/child as same, not two different process?

If I put something below the closing } of if(pid==0), does it get executed in parent or both?
eg: while() condition and any code below while condition should only be executed by the parent.

You don't check that execl() doesn't return. If it does, there has been an error, and there is NO exec'ed process.

You don't check that wait() doesn't return an error. If it does, your code will loop forever.

"This ain't like dusting crops boy", you need to check everything all the time, not when someone nags you into doing it.

Can you tell me how you do this?

For execl():

execl();
_exit(EXIT_FAILURE);

For wait() am not so sure how to do this.

Perhaps

do {
  exited_pid = wait( &status );
  // if/else logic for normal exit and errors
} while ( exited_pid != pid );

Perhaps

do {
  exited_pid = wait( &status );
  // if/else logic for normal exit and errors
} while ( exited_pid != pid );

If I am only forking one process in progA and no forking in progB(just execl in method main), any reason why I need to worry about this?

I was under the impression that it wasn't working, and you couldn't figure out why.

But I've seen your other "exec" thread as well.

Post your latest code and latest observations.

When I run this, I get funny characters displayed continuously on my shell.

Here is my programA code:

#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>


int main (int argc, char *argv[])
{

int pid, exited_pid; /* process identifier */
int status;
	/* Open system logger */
	openlog( "progA", LOG_PID, LOG_LOCAL1 ); 

	
    pid = fork();
    syslog(LOG_ERR,"ERROR: forked process id = %d.\n", pid);
    if ( pid < 0 )
        		 { 
        			syslog(LOG_ERR,"Cannot fork!!");
        			exit(1);
        		 }
     if ( pid == 0 )
        	{ /* Child process */

        	 execl("./progb",0);
        	 _exit(EXIT_FAILURE);
        	}
      do{
    	  exited_pid = wait(&status);
      }
      while (exited_pid != pid)
                /* empty */ ;


    syslog(LOG_ERR,"End \n");
    exit (0);
}

Here is my programB code:

#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define SIZE 256
char f1[SIZE],f2[SIZE];


int main (int argc, char *argv[])
{
int i=0;
	/* Open system logger */
	openlog( "progB", LOG_PID, LOG_LOCAL2 ); 

	
    execl("/bin/gzip","/bin/gzip","-c","../data/data_.txt",">","./data/data.gz",0);
    syslog(LOG_INFO,"INFO: file: %s, gzip file: %s\n", f1, f2);

}

In my syslog I see pid printed twice from progA. I don't know why. Also progB syslog never get logged for what ever reason.

Dec 25 20:18:08 localhost progA[4800]: ERROR: forked process id = 0.
Dec 25 20:18:08 localhost progA[4799]: ERROR: forked process id = 4800.
Dec 25 20:18:09 localhost progA[4799]: End

execl doesn't understand ">" as meaning redirection.

> In my syslog I see pid printed twice from progA. I don't know why.
Because it appears AFTER the fork(), and before the conditionals which switch between parent and child. So it happens in both.

> Also progB syslog never get logged for what ever reason.
Perhaps because it's a low priority LOG_INFO rather than a high priority LOG_ERR.
Also, f1 and f2 are not initialised (unless that's something you've snipped)
Also, it appears AFTER the execl() call, so it can only ever execute if the execl FAILS (I've said this before remember).

Oh, and one more thing, your indentation sucks.
Configure your IDE to only use 4 spaces for indentation (any decent code editor will allow you to do this somewhere). Your IDE may be able to do the right thing with a mix of space and tab characters, but forums as a rule make a mess of it.
Use the "preview" feature of the forum post to make sure your code looks exactly like what you're seeing in your IDE, indentation wise at least.

execl doesn't understand ">" as meaning redirection.

How I can get the gzipping: execl("/bin/gzip","/bin/gzip","-c","../data/data_.txt",">","./data/data.gz",0);
to work from a C-program?

Also, it appears AFTER the execl() call, so it can only ever execute if the execl FAILS (I've said this before remember).

I understand it now.

Oh, and one more thing, your indentation sucks. Configure your IDE to only use 4 spaces for indentation (any decent code editor will allow you to do this somewhere). Your IDE may be able to do the right thing with a mix of space and tab characters, but forums as a rule make a mess of it.

Use the "preview" feature of the forum post to make sure your code looks exactly like what you're seeing in your IDE, indentation wise at least.

I am just using default Eclipse CDT setup. I was just not tabbing properly.

Also I think I need to pass an array of string to execv like so?

#define SIZE 256
char f1[SIZE],f2[SIZE];

i =0;
sprintf(f1, "../data/data%d_.txt", i);
sprintf(f2, "../data/data%d.gz", i);

char *argv[6], *c1, *c2,*c3,*c5;
strcpy(c1, "/bin/gzip");
strcpy(c2, "/bin/gzip");
strcpy(c3, "-c");
strcpy(c5, ">");

argv[0]=c2;
argv[1]=c3;
argv[2]=f1;
argv[3]=c5;
argv[4]=f2;
argv[5]=(char*)0;

and call execv like this:
execv(c1, argv);

can someone tell me how I can call gzip from C?

I think something like this (untested) would work.

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main ( ) {
    pid_t   pid;
    pid = fork();
    if ( pid == 0 ) {
        char *argv[4];
        int fd = open("bar.zip",O_CREAT | O_TRUNC | O_WRONLY);
        dup2(fd,STDOUT_FILENO);
        argv[0] = "/bin/gzip";
        argv[1] = "-c";
        argv[2] = "test.txt";
        argv[3] = NULL;
        execv( argv[0], argv );
    } else if ( pid != (pid_t)-1 ) {
        int status;
        pid_t   waitpid = wait(&status);
    } else {
        fprintf(stderr,"Fork failed\n" );
    }
    return 0;
}

In order to achieve the redirection, the desired output file is opened for writing, then dup2 is called to replace the existing stdout with the file descriptor of the opened file.

I ran it. But I have problem with the output file. I can't gunzip it. I changed bar.zip on the second run to bar.gz. What is cap T in permission for the file?

--wx-wx--T 1 jobs jobs  432940 Dec 27 13:37 bar.gz
-r----x--T 1 jobs jobs  432940 Dec 27 13:34 bar.zip
[jobs@localhost proj1]$ gunzip bar.gz 
gunzip: bar.gz: Permission denied

> gunzip bar.gz
Your file seems to lack read permissions.
Since it needs to read the file, and it doesn't have read permissions, it's going to fail.

There are some very strange permissions on those files. Have you been messing with the umask() function?

> There are some very strange permissions on those files. Have you been messing with the umask() function?
I didn't play with umask()
I just cut and pasted it and complied with gdb option and ran it inside gdb. Do I have to do setuid inside the c program when it's forking a process that creates a file?

If I compile it without gdb and ran it normal, I get the file permission as:
--wx-wx--T bar.gz

On the linux terminal, I changed the permission to 770 and gunzipped. Bar contents looks good. And the permisson T disappears after chmod 770. I will quote this from this site: capital T sticky Bit

Using the sicky bit, the administrator could ensure that once a given student created content in their respective folder, no other student could come in and delete it.

Here's how it looks:

drwxr-xr-t 1 alice alice 4.4K 2007-01-01 09:21 Alice

Remember that if "everyone" (other) doesn't have execute permissions on the directory it'll be a capital T instead of lowercase.

Everything looks good to me. I can just do the gzipping in a process and have the main process wait for it to complete. Then fork another process to change zip file permission.

This technique should work. I will give it a try. Salem, thank you very much for the help.

> Then fork another process to change zip file permission.
Or just use the chmod() API call instead of running the chmod command.

commented: jobs: thanks for the help. +1

Salem, in the above code you do: (pid_t)-1, what does this do? Type cast the -1 to pid_t?
Can I run fork in a function other than main? Many example on google show it main.
Can I do parent (programA) create a process, then that child (programB) process creates another child process, Grand Parent(programA spawn a process to run programB)->Parent(programB process)->Child(programB spawn a process)?

I got it to work. Whoo hoo! Salem, you're C SuperMan. Thanks.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.