I believe there's a way to synchronize two processes using pipes, but I'm unsure on how to implement it. In my code both the child and father process execute its code at the same time, I would like for one process to wait for the other. For example, using a pipe to block one process until the other process is done.
My code:
int main()
{
int one[2];
int two[2];
int x=0;
char messageRead[256], messageRead2[256], messageWrite[256], messageWrite2[256];
pipe(one);
pipe(two);
pid_t pid = fork();
if(pid == 0) //child process
{
while (x==0) //loop until condition is met (didn't write the condition yet, just testing)
{
std::cout << "Child process.\n\n";
std::cin >> messageWrite;
write(one[1], messageWrite, 256);
read(two[0], messageRead2, 256 );
}
}
else if(pid>0) //father process
{
while(x==0)
{
std::cout << "Father process.\n\n";
std::cin >> messageWrite;
write(two[1], messageWrite2, 256);
read(one[0], messageRead, 256);
}
}
}
Right now, both processes go back and forth, like I want but they both execute at the same time like this:
Father process.
Child process.
user input here
user input here
Father process.
Child process.
user input here
user input here
Child process.
Father process.
user input here
user input here
etc...
One method that can work rather well is to simply rely on pipes blocking if you try to read and there's nothing in them. With that (configured if necessary), you define one process to own the resource you're protecting and while it continues to own this resource, it uses it as it wishes (and the pipe is empty).
When the resource owner wishes to relinquish the resource, it writes a token into the pipe. This token can be anything that makes sense to you… a simple meaningless piece of data, or something that has meaning.
When either process wishes to own the resource (while it doesn't already), it reads the pipe… this blocks it until something is in there. When the read is successful, that process now owns the resource.
You can do this with non-blocking I/O also, as long as you keep track in each process if you own the resource or not.
The problem in the code you've provided in your question is that both processes write to the other's pipe right away, allowing the other end's read to be successful without any delay.
Related
I don't know if this is the best way but I have a random number of child processes who have beed execed and wanted to implement a way to kill them without using ctrl+c. I was thinking of keeping a set of their pids and then check that set whenever I want to kill them from the parent process.
The way I was trying to do it was something like this
set<pid_t> pids;
pid_t id = fork();
if(id == 0)
{
pids.insert(getpid());
execlp("./somewhere", "./somewhere", something.c_str(), NULL);
cout << "Didn't exec" << endl;
exit(0);
}
for(auto i : pids)
{
kill(i, something?)
}
I still don't quite know how to use the kill function or how pids work so I don't know if this will work in any way, I just did a simple project in c for college and though I could try something more complex in c++.
Anyways, the objective of this is to be able to have the parent process kill a single child process out of an undefined number of running child processes, or kill them all whenever the user writes quit
kill() on pid 0 sends the signal to all members of the calling process group:
If pid is 0, sig shall be sent to all processes (excluding an
unspecified set of system processes) whose process group ID is equal
to the process group ID of the sender, and for which the process has
permission to send a signal.
If you want to kill only certain processes (as seems to be your case) take a look to Grouping child processes with setpgid()
My program has the following parent child layout:
int main() {
std::vector<pid_t> kids;
pid_t forkid = fork();
if (forkid == 0) {
//child process
pid_t fork2 = fork()
if (fork2 == 0) {
// child process
}else {
//parent
kids.push_back(fork2);
}
}else {
// code here
kids.push_back(forkid);
}
// Not killing the fork2 process - only the first process(forkid) is terminated
for (pid_t k : kids) {
int status;
kill(k, SIGTERM);
waitpid(k, &status, 0);
}
}
I am not able to kill the child process (fork2) - the first process gets terminated. The kids vector seems to only contain the process id of the first process. Never gets the pid of the child process.
What am I doing wrong here. Any help will be appreciated. Thanks.
std::vector<pid_t> kids;
pid_t forkid = fork();
fork() creates a complete duplicate image of the parent process as its child process. Emphasis on: duplicate.
This means that, for example, the child process has its very own kids vector, that has nothing to do, whatsoever, with the parent process's original kids vector.
Since this is the very first thing that happens in main, this is really no different than you running this executable twice, individually as two distinct and separate processes, instead of forking off a process. You can't expect the kids vector in one of the two processes to have any effect on the kids vector in the other one.
The first child process creates a 2nd child process, and also adds the 2nd child process's pid into its own kids vector. But that's just the first child process's kids vector.
The only process id that the original parent process's kids vector ends up having is the first child's process it, so that's all you get to SIGTERM.
Your options are:
Restructure your logic so that both child process get created by the parent process, so it, alone, puts their process ids into its kids vector.
Instead of using fork use multiple execution threads, and the same process. However, neither std::vector, nor any other C++ library container is thread safe. A massive pile of code will need to be written to properly synchronize the threads, in order for things to work themselves out correctly (not to mention that the analogue for the SIGTERM, with respect to multiple execution threads, needs to be invented in some way).
The simplest alternative is the first one.
I have a little problem, I wrote a program, server role, doing an infinite loop waiting for client requests.
But I would like this program to also return his pid.
Thus, I think I should use multithreading.
Here's my main :
int main(int argc, char **argv) {
int pid = (int) getpid();
int port = 5555
ServerSoap *servsoap;
servsoap = new ServerSoap(port, false);
servsoap->StartServer(); //Here starts the infinite loop
return pid; //so it never executes this
}
If it was bash scripting I would add & to run it in background.
Shall I use pthread ? And how to do it please ?
Thanks.
eo
When a program returns (exits), all running threads terminate, so you can't have a background thread continue to run.
In addition, the int return value of main is (usually) truncated to a 7-bit value, so you don't have enough space to return a full pid.
It'd be better just to print the pid to stdout using printf.
If you put the infinite loop in a separate thread, and then return from main it will kill the whole process including your new thread. One solution, keeping to threads, is to make a detached thread. A better solution is probably to create a new process:
int main()
{
int pid = fork();
if (pid == -1)
perror("fork");
else if (pid == 0)
{
ServerSoap serversoap(5555, false);
serversoap.StartServer();
}
return pid;
}
Edit: Also note the limit to the return value from main as noted in the answer from ecatmur.
I have a feeling that you're trying to implement daemon.
To add to #ecatmur answer, if no error has happened program should always return 0 on termination.
PID is usually saved in some file, often times in /var/run/ directory. Some programs use /tmp/ directory.
Your main is attempting to do what your server should do. You're confusing a couple patterns here.
Pattern #1: Daemon
Think of the main as the program that, when on, accepts client requests and performs operations with them. The main has to wait for requests if this is the structure of the program. When a request is received, only then do you perform the requested operation. The main serves only to turn on or off this service. Normally this type of behavior is handled by default with threads. The listener activates a thread calling specific methods with information regarding the request, for instance. Unless you require threads for the work you need done, you shouldn't require threads for this.
Pattern #2: Tool
Alternatively, you could simply call this program as a tool. You'd still need a web service, but this program could be separate from that. Apart from what your tool should do, you shouldn't require threads for this.
In either case, I don't think what you're looking for is to implement threading. You're simply activating a server which does nothing. You should probably look into adding request handlers instead.
I have managed to fork and exec a different program from within my app. I'm currently working on how to wait until the process called from exec returns a result through a pipe or stdout. However, can I have a group of processes using a single fork, or do I have to fork many times and call the same program again? Can I get a PID for each different process ? I want my app to call the same program I'm currently calling many times but with different parameters: I want a group of 8 processes of the same program running and returning results via pipes. Can someone please point me to the right direction please ? I've gone through the linux.die man pages, but they are quite spartan and cryptic in their description. Is there an ebook or pdf I can find for detailed information ? Thank you!
pid_t pID = fork();
if (pID == 0){
int proc = execl(BOLDAGENT,BOLDAGENT,"-u","2","-c","walkevo.xml",NULL);
std::cout << strerror(errno) << std::endl;
}
For example, how can I control by PID which child (according to the parameter xml file) has obtained which result (by pipe or stdout), and thus act accordingly? Do I have to encapsulate children processes in an object, and work from there, or can I group them altogether?
One Fork syscall make only one new process (one PID). You should organize some data structures (e.g. array of pids, array of parent's ends of pipes, etc), do 8 fork from main program (every child will do exec) and then wait for childs.
After each fork() it will return you a PID of child. You can store this pid and associated information like this:
#define MAX_CHILD=8
pid_t pids[MAX_CHILD];
int pipe_fd[MAX_CHILD];
for(int child=0;child<MAX_CHILD;child++) {
int pipe[2];
/* create a pipe; save one of pipe fd to the pipe_fd[child] */
int ret;
ret = fork();
if(ret) { /* parent */
/* close alien half of pipe */
pids[child] = ret; /* save the pid */
} else { /* child */
/* close alien half of pipe */
/* We are child #child, exec needed program */
exec(...);
/* here can be no more code in the child, as `exec` will not return if there is no error! */
}
}
/* there you can do a `select` to wait data from several pipes; select will give you number of fd with data waiting, you can find a pid from two arrays */
It's mind-bending at first, but you seem to grasp that, when you call fork( ):
the calling process (the "parent") is
essentially duplicated by the
operating system and the duplicate process
becomes the "child"
with a unique PID all its own;
the returned value from the fork( )
call is either: integer
0,1 meaning that the
program receiving the 0 return is the
"child"; or it is the non-zero integer PID
of that forked child; and
the new child process is entered into
the scheduling queue for execution.
The parent remains in the scheduling
queue and continues to execute as
before.
It is this ( 0 .xor. non-0 ) return from fork( ) that tells the program which role it's playing at this instant -- 0 returned, program is the child process; anything else returned, program is the parent process.
If the program playing the parent role wants many children, he has to fork( ) each one separately; there's no such thing as multiple children sharing a fork( ).
Intermediate results certainly can be sent via a pipe.
As for calling each child with different parameters, there's really nothing special to do: you can be sure that, when the child gets control, he will have (copies of) exactly the same variables as does the parent. So communicating parameters to the child is a matter of the parent's setting up variable values he wants the child to operate on; and then calling fork( ).
1 More accurately: fork( ) returns a value of type pid_t, which these days is identical to an integer on quite a few systems.
It's been a while since I've worked in C/C++, but a few points:
The Wikipedia fork-exec page provides a starting point to learn about forking and execing. Google is your friend here too.
As osgx's answer says, fork() can only give you one subprocess, so you'll have to call it 8 times to get 8 processes and then each one will have to exec the other program.
fork() returns the PID of the child process to the main process and 0 to the subprocess, so you should be able to do something like:
int pid = fork();
if (pid == 0) {
/* exec new program here */
} else {
/* continue with parent process stuff */
}
is there a way for a forked child to examine another forked child so that, if the other forked child takes more time than usual to perform its chores, the first child may perform predefined steps?
if so, sample code will be greatly appreciated.
Yes. Simply fork the process to be watched, from the process to watch it.
if (fork() == 0) {
// we are the watcher
pid_t watchee_pid = fork();
if (watchee_pid != 0) {
// wait and/or handle timeout
int status;
waitpid(watchee_pid, &status, WNOHANG);
} else {
// we're being watched. do stuff
}
} else {
// original process
}
To emphasise: There are 3 processes. The original, the watcher process (that handles timeout etc.) and the actual watched process.
To do this, you'll need to use some form of IPC, and named shared memory segments makes perfect sense here. Your first child could read a value in a named segment which the other child will set once it has completed it's work. Your first child could set a time out and once that time out expires, check for the value - if the value is not set, then do what you need to do.
The code can vary greatly depending on C or C++, you need to select which. If C++, you can use boost::interprocess for this - which has lots of examples of shared memory usage. If C, then you'll have to put this together using native calls for your OS - again this should be fairly straightforward - start at shmget()
This is some orientative code that could help you to solve the problem in a Linux environment.
pid_t pid = fork();
if (pid == -1) {
printf("fork: %s", strerror(errno));
exit(1);
} else if (pid > 0) {
/* parent process */
int i = 0;
int secs = 60; /* 60 secs for the process to finish */
while(1) {
/* check if process with pid exists */
if (exist(pid) && i > secs) {
/* do something accordingly */
}
sleep(1);
i++;
}
} else {
/* child process */
/* child logic here */
exit(0);
}
... those 60 seconds are not very strict. you could better use a timer if you want more strict timing measurement. But if your system doesn't need critical real time processing should be just fine like this.
exist(pid) refers to a function that you should have code that looks into proc/pid where pid is the process id of the child process.
Optionally, you can implement the function exist(pid) using other libraries designed to extract information from the /proc directory like procps
The only processes you can wait on are your own direct child processes - not siblings, not your parent, not grandchildren, etc. Depending on your program's needs, Matt's solution may work for you. If not, here are some other alternatives:
Forget about waiting and use another form of IPC. For robustness, it needs to be something where unexpected termination of the process you're waiting on results in your receiving an event. The best one I can think of is opening a pipe which both processes share, and giving the writing end of the pipe to the process you want to wait for (make sure no other processes keep the writing end open!). When the process holding the writing end terminates, it will be closed, and the reading end will then indicate EOF (read will block on it until the writing end is closed, then return a zero-length read).
Forget about IPC and use threads. One advantage of threads is that the atomicity of a "process" is preserved. It's impossible for individual threads to be killed or otherwise terminate outside of the control of your program, so you don't have to worry about race conditions with process ids and shared resource allocation in the system-global namespace (IPC objects, filenames, sockets, etc.). All synchronization primitives exist purely within your process's address space.