call main(argc, argv) from fork() - c++

There is mostly nothing found through search about calling main - so I am going to guess this question is that fundamentally 'off'.
The suggested questions provides this C# question "Calling Main() from another class" the answer there is that you don't, use a subfunction under Main() and call that; so my assumption is that the same answer applies here with fork().
void somefunction ()
{
pid_t pid;
pid = fork();
if (pid == 0) {
char *p;
char *argv[] = { (char*)spawn_count, (char*)gradiant, (char*)i, (char*)(i+spread), p };
main(5, **argv);
}
else if (pid == -1)
cout << "ERROR: can't fork" << endl;
else ; //PID == 1,
}
This compiles in g++ with "error: 'main' was not declared in this scope"
Questions:
How is main(argc, argv) scoped? I can follow the process in windows with LPTSTR.
After fork(), to start the child from main(), how is this done?
After fork(), where is the child, in the same function that called child, in main?

Why do you want to call main?
Could you not just fork in main something like below:
int main()
{
pid_t pid;
pid = fork();
if(pid < 0 )
{
// Error some issue forking
}
if (pid == 0) {
// Child related processing here
}
else {
// parent related processing here
}
}
Fork returns twice once for parent and once for child and at the same point from where the fork system call was made.
You could refer this link to read more: http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

For anyone who falls into the same trap I did - Linux and Windows parallel processing works very differently.
In Windows, you call the program again and pass arguments through main()
In Linux, you call fork() then call any function you want from within your program, just like with any other function. This approach is super easy compared to the 'crap' you go through to fork windows.
After understanding this distinction, I immediately removed windows from my laptop and installed Linux :)

Related

How to use signals in C++ and How they react?

I am trying to learn all interactions about signals and I discovered a funny interaction in it I can't understand.
Here's an abstract of the program, Im instructed to do execvp with grandchild, while child needs to wait for grandchild to finish. It runs correctly when without any signal interactions.
void say_Hi(int num) { printf("Finished\n"); }
int main() {
int i = 2;
char *command1[] = {"sleep", "5", NULL};
char *command2[] = {"sleep", "10", NULL};
signal(SIGCHLD, SIG_IGN);
signal(SIGUSR1, say_Hi);
while(i > 0) {
pid_t pid = fork();
if (pid == 0) {
pid_t pidChild = fork();
if (pidChild == 0) {
if (i == 2) {
execvp(command1[0], command1);
} else {
execvp(command2[0], command2);
}
} else if (pidChild > 0) {
waitpid(pidChild, 0, 0);
// kill(pid, SIGUSR1);
printf("pid finished: %d\n", pidChild);
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
} else {
//parent immediately goes to next loop
i--;
}
}
cin >> i; //just for me to pause and observate answers above
return 0;
}
As shown above, kill(pid, SIGUSR1); is commented, the program runs correctly.
Output:
pid finished: 638532 //after 5 sec
pid finished: 638533 //after 10 sec
However, when it is uncommented. Output becomes:
Finished
pid finished: 638610 //after 5 sec
Finished
Finished
Finished
Finished
pid finished: 638611 //after 5 sec too, why?
Finished
I would like to ask:
The whole program finished at once after 5 secs and a total of 6 "Finished" is printed out. Why is so?
Is there a way for me to modify it so that say_Hi function run in a total of two times only, in a correct time interval?
Please forgive me if my code looks stupid or bulky, I'm a newbie in programming. Any Comments about my code and help are appreciated!
void say_Hi(int num) { printf("Finished\n"); }
printf cannot be called in a signal handler. None of the C or the C++ library functions (with few exceptions) can be called in the signal handler. You can't even allocate or delete any memory from a signal handler (using either the C or the C++ library), except by using low-level OS calls like brk() or sbrk(). This is because of a very simple reason: that none of the C or the C++ library functions are signal-safe (with very few exceptions). Only function calls that are explicitly designated as "signal-safe" can be called from a signal handler. None of the C or C++ library functions or classes (with few exceptions) are signal-safe. The End.
The only thing that can be called from a signal handler are low-level operating system calls, like read() and write(), that operate directly on file handles. They are, by definition, signal-safe.
For this simple reason the shown code, when it comes to signals, is undefined behavior. Trying to analyze or figure out your programs behavior, from that respect, such as why or why not you see this message, is completely pointless. It cannot be logically analyzed. This is undefined behavior.
Answer:
kill(getpid(), SIG_USR1);

fork() and exec() Two Child Processes

I am calling fork() twice to create two child processes. I want child process A to do an exec() call and child process B to also do an exec() call. The problem I am having with the given code is that after the first exec() from child process A, the next fork() does not seem to occur and the program exits. I think that it has to do with how exec() overlays the parent process. What I want to accomplish is to call exec() from each of the child processes created by fork().
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
int main() {
pid_t cpid_a, cpid_b;
cpid_a = fork();
if(cpid_a < 0) {
std::cout << "Fork failed." << '\n';
return 1;
}
else if(cpid_a == 0) { // code for child process A
execlp("/bin/ls", "ls", NULL);
cpid_b = fork();
if(cpid_b < 0) {
std::cout << "Fork failed." << '\n';
return 1;
}
else if(cpid_b == 0) { // code for child process B
execlp("/bin/ls", "ls", NULL);
}
}
else { // code for parent process
while(wait(NULL) != -1);
}
return 0;
}
else if(cpid_a == 0) { // code for child process A
execlp("/bin/ls", "ls", NULL);
If this calls succeeds, the following statement, and nothing that follows will ever be executed. That's how exec() works. The immediately-following fork() never occurs. That's simply how exec() works. If exec() succeeds, it never returns. The replacement process gets executed in its place.
You even added the 100% correct comment, above: "code for child process A". Everything inside the if() statement is "code for child process A", and gets executed when fork() returns 0.
You also correctly stated that you want the parent process to fork a second process. Well, you need to have that code obviously get executed by the parent process, and not the child process:
else if(cpid_a == 0) { // code for child process A
execlp("/bin/ls", "ls", NULL);
exit(1);
} else {
cpid_b = fork();
// The rest of the code.
Now, the parent process goes ahead and fork() a second time, proceeded on the rest of your plan.
P.S. The exit() is just for a good measure. The only time exec() returns is when exec() fails to execute the given process. Highly unlikely, in the case of /bin/ls; if it's missing you have bigger problems to worry about. Still, that's the technically correct thing to do, since continuing execution at that point will result in complete chaos. Again, if /bin/ls is missing that's going to be the least of the problems, but this can also happen if, say, the system ran out of memory and can't execute it for that reason; in which case there's no need to add fuel to the fire; but rather have the process die anyway.

Waiting for system call to finish

I've been tasked to create a program that takes a text file that contains a list of programs as input. It then needs to run valgrind on the programs (one at a time) until valgrind ends or until the program hits a max allotted time. I have the program doing everything I need it to do EXCEPT it isn't waiting for valgrind to finish. The code I'm using has this format:
//code up to this point is working properly
pid_t pid = fork();
if(pid == 0){
string s = "sudo valgrind --*options omitted*" + testPath + " &>" + outPath;
system(s.c_str());
exit(0);
}
//code after here seems to also be working properly
I'm running into an issue where the child just calls the system and moves on without waiting for valgrind to finish. As such I'm guessing that system isn't the right call to use, but I don't know what call I should be making. Can anyone tell me how to get the child to wait for valgrind to finish?
I think that you are looking for fork/execv. Here is an example:
http://www.cs.ecu.edu/karl/4630/spr01/example1.html
An other alternative could be popen.
You can fork and exec your program and then wait for it to finish. See the following example.
pid_t pid = vfork();
if(pid == -1)
{
perror("fork() failed");
return -1;
}
else if(pid == 0)
{
char *args[] = {"/bin/sleep", "5", (char *)0};
execv("/bin/sleep", args);
}
int child_status;
int child_pid = wait(&child_status);
printf("Child %u finished with status %d\n", child_pid, child_status);

C++ : fork/exec or pthread?

I'm writing a program, and once a button is pushed, I have to execute a server process (that will stop only if I decide to kill him).
To execute this process, I decided to use fork/execv mechanism :
void Command::RunServer() {
pid = fork();
if (pid==0) {
chdir("./bin");
char str[10];
sprintf(str,"%d",port);
char *argv[] = {"./Server", str};
execv("./Server",argv);
}
else {
config->pid = pid;
return;
}
}
And in the method "button pushed", I do:
command->RunServer();
It seemed to work nicely a few days ago... and now i get error :
main: xcb_io.c:221: poll_for_event: Assertion `(((long) (event_sequence) - (long) (dpy->request)) <= 0)' failed.
Should I try to switch to pthread? Did I do something bad?
Thanks,
eo
When you do fork() all file descriptors of your process are duplicated in the new one. And when you do exec*() all file descriptors are also kept, unless they are marked with the flag FD_CLOEXEC.
My guess is that some fd used by some library (Xlib, probably) is inherited by the new process, and that the duplication is causing chaos in your program.
In these cases is useful the BSD function closefrom() (closefrom(3)) if you want to keep the standard I/O opened. Unfortunately, in linux there is no such function, so you have to do a close-all loop or similar cruft:
int open_max = sysconf (_SC_OPEN_MAX);
for (int i = 3; i < open_max; i++)
close(i);
You can read more about this problem here.
In the call to execv, argv has to be terminated by a null pointer.
The preceding line should be:
char* argv[] = { "./Server", str, NULL };

How can I run an external program without waiting for it to exit?

I'm trying to execute an external program from inside my Linux C++ program.
I'm calling the method system("gedit") to launch an instance of the Gedit editor. However my problem is while the Gedit window is open, my C++ program waits for it to exit.
How can I call an external program without waiting for it to exit?
You will need to use fork and exec
int fork_rv = fork();
if (fork_rv == 0)
{
// we're in the child
execl("/path/to/gedit", "gedit", 0);
// in case execl fails
_exit(1);
}
else if (fork_rv == -1)
{
// error could not fork
}
You will also need to reap your child so as not to leave a zombie process.
void reap_child(int sig)
{
int status;
waitpid(-1, &status, WNOHANG);
}
int main()
{
signal(SIGCHLD, reap_child);
...
}
In regards to zombie processes, you have a second option. It uses a bit more resources (this flavor forks twice), but the benefit is you can keep your wait closer to your fork which is nicer in terms of maintenance.
int fork_rv = fork();
if (fork_rv == 0)
{
fork_rv = fork();
if (fork_rv == 0)
{
// we're in the child
execl("/path/to/gedit", "gedit", 0);
// if execl fails
_exit(1);
}
else if (fork_rv == -1)
{
// fork fails
_exit(2);
}
_exit(0);
}
else if (fork_rv != -1)
{
// parent wait for the child (which will exit quickly)
int status;
waitpid(fork_rv, &status, 0);
}
else if (fork_rv == -1)
{
// error could not fork
}
What this last flavor does is create a child, which in turns creates a grandchild and the grandchild is what exec's your gedit program. The child itself exits and the parent process can reap it right away. So an extra fork but you keep all the code in one place.
Oh, let me say it!
http://en.wikipedia.org/wiki/Fork-exec
Fork! :)
First, did you try to launch in background with system("gedit&")?
If that does not work, try spawning a new thread and running gedit from there.
I presume that you are not concerned with the result of the edit, or the contents of the edited file?