I'm trying to have a parent process wait on multiple child processes signalling, before the parent continues, using an array of unnamed semaphores (one per child process). However, when using sem_wait(), the parent process waits indefinitely, while sem_trywait() returns a "resource temporarily unavailable" error, and continues without the child processes having signalled. Neither sem_init() nor sem_post() return an error.
Relevent portion of the code:
int numsems = concurrent_instrs.size();
std::cout << "Num sems: " << numsems << "\n";
// create semaphores
sem_t* sems = new sem_t[numsems];
for (int i = 0; i < numsems; i++)
{
if (sem_init(&sems[i], 1, 0) < 0)
{
perror("sem initialization failed");
exit(1);
}
}
int child_num = 0;
// perform all calculations in block concurrently
for(unsigned int i = 0; i < concurrent_instrs.size() && !isChild; i++)
{
int pid = fork();
if (pid == -1)
{
perror("Error forking:");
exit(1);
}
if (pid == 0)
{
isChild = true;
instr = concurrent_instrs[i];
}
else
{
child_num++;
}
}
if (isChild)
{
std::cout << "Child process " << child_num << " calculating: " << instr << "\n";
perform_calculation(instr, input_vars, internal_vars, shm_input, shm_internal);
std::cout << "Child process " << child_num << " finished calculating\n";
if (sem_post(&sems[child_num]) < 0)
{
perror("Child signal failed");
}
std::cout << "Child "<< child_num << " signalled\n";
// detach from shared memory
if (shmdt(shm_input) < 0)
{
perror("child shm_input detach failed");
}
if (shmdt(shm_internal) < 0)
{
perror("child shm_internal detach failed");
}
exit(0);
}
else
{
// parent waits for all children to finish
for (int i = 0; i < numsems; i++)
{
std::cout << "Waiting on subprocess " << i << " of " << numsems << "\n";
if (sem_trywait(&sems[i]) < 0)
perror("Parent wait failed");
else
std::cout << "Parent wait " << i << " working\n";
}
std::cout << "Finished waiting\n";
// destroy semaphores
for (int i = 0; i < numsems; i++)
{
if(sem_destroy(&sems[i]) < 0)
{
perror("Sem destroy failed");
exit(2);
}
else
{
std::cout << "Sem " << i << " destroyed\n";
}
}
delete[] sems;
}
Am I setting something up incorrectly, or just misunderstanding how to use semaphores in this situation?
Edit to add: sem_wait() encounters the error regardless of whether the child processes call sem_post() before or after the wait.
The semaphores allocated with sem_t* sems = new sem_t[numsems]; are not in the shared memory. Therefore each process has its own copy, and posting in the child doesn't affect the parent.
The parent's copy remains locked. sem_trywait fails with EAGAIN, which translates to resource temporarily unavailable explanation.
Related
I'm currently trying to convert a multithreaded LAN tic tac toe game so it compiles / works on my Windows system. I'm quite new to networking but I've managed to translate a lot of the system calls to Socket API calls however I am having trouble understanding how to convert the 'pthread' functions. Most of the questions I see online are asking how to compile it, but I want to change it instead of adding new libraries etc.
Can someone please shed some light on what exactly pthread does and how I can change it to compile in the native windows environment.
Thanks!
Main Function
pthread_mutex_t games_lock = PTHREAD_MUTEX_INITIALIZER;
int main() {
//Initialise Winsock
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0) {
std::cerr << "Can't start Winsock, Err #" << wsResult << endl;
}
// Signals used to kill the server gracefully
if (signal(SIGINT, sig_handler) == SIG_ERR)
{
perror("Can't catch SIGINT");
exit(1);
}
if (signal(SIGTERM, sig_handler) == SIG_ERR)
{
perror("Can't catch SIGTERM");
exit(1);
}
// Initialize the server and get the server's socket
server_sock = init_server();
int new_socket = 0;
// Infinitely accept clients and spawning threads
while (true)
{
// Wait for a client, and then accept
if ((new_socket = accept(server_sock, NULL, NULL)) < 0)
{
perror("Failed to accept client");
closesocket(server_sock);
exit(1);
}
cout << "New client connected" << endl;
// Spawn thread to handle the client
pthread_t threadid;
pthread_create(&threadid, NULL, handle_client, (void*)&new_socket);
}
return 0;
}
Client Handle Function
{
int client_sock = *(int*)arg;
char buffer[BUF_SIZE];
bool client_connected = true;
char temp = '\0';
int row = 0, col = 0;
int i = 0;
// Create the player
Player player(client_sock);
// Always handle the client
while (client_connected)
{
// Process commands or pass game data
if (player.GetMode() == COMMAND)
{
// Read a line of text or until the buffer is full
for (i = 0; (i < (BUF_SIZE - 1)) && temp != '\n' && client_connected; ++i)
{
// Receive a single character and make sure the client is still connected
if (recv(client_sock, &temp, 1, 0) == 0)
client_connected = false;
else
buffer[i] = temp;
}
// Reset temp so we don't get an infinite loop
temp = '\0';
buffer[i] = '\0';
buffer[i - 1] = '\0';
cout << "Received command \"" << buffer << "\" from " << player.GetName() << endl;
buffer[i - 1] = '\n';
// If there's an invalid command, tell the client
if (!ProcessCommand(buffer, player, client_connected))
SendStatus(player.GetSocket(), INVALID_CMD);
}
else if (player.GetMode() == INGAME)
{
// Get the game the player is a part of
pthread_mutex_lock(&games_lock);
auto game = find_if(game_list.begin(), game_list.end(),
[player](TTTGame* game) { return game->HasPlayer(player); });
auto end = game_list.end();
pthread_mutex_unlock(&games_lock);
// Something horrible has gone wrong
if (game == end)
cout << "Somehow Player " << player.GetName() << " isn't a part of a game but is INGAME" << endl;
else
{
StatusCode status;
client_connected = ReceiveStatus(player.GetSocket(), &status);
// If the player is still connected, then perform the move
if (client_connected)
{
switch (status)
{
case MOVE:
// Pass the row and column right along
ReceiveInt(player.GetSocket(), &row);
ReceiveInt(player.GetSocket(), &col);
cout << "Received moved from " << player.GetName()
<< ": row=" << row << ", col=" << col << endl;
SendStatus((*game)->GetOtherPlayer(player).GetSocket(), MOVE);
SendInt((*game)->GetOtherPlayer(player).GetSocket(), row);
client_connected = SendInt((*game)->GetOtherPlayer(player).GetSocket(), col);
cout << "Sent move to " << (*game)->GetOtherPlayer(player).GetName() << endl;
break;
case WIN:
cout << player.GetName() << " won a game against " << (*game)->GetOtherPlayer(player).GetName() << endl;
client_connected = false;
break;
case DRAW:
cout << player.GetName() << " tied against " << (*game)->GetOtherPlayer(player).GetName() << endl;
client_connected = false;
break;
default:
client_connected = SendStatus(player.GetSocket(), INVALID_CMD);
}
}
}
}
}
// The client disconnected on us D:
cout << "Player \"" << player.GetName() << "\" has disconnected" << endl;
DisconnectPlayer(player);
closesocket(client_sock);
WSACleanup();
return (void*)0;
}
These are just some examples of the code. I am happy to post more if needed.
I have an assignment where I have to write a subshell in C++. Essentially, I am forking (if the input is not jobs or exit) and in the child process, I am calling exec to run the command. It needs to run alongside the parent process, so for example if I call sleep 100, the program should immediately be ready to run the next command since the parent is not "waiting" for it since I am using WNOHANG. However, my issue is when I need to track the actual state- if sleep is still running, I want to be able to get that the command is still running, but I am unable to do so. It always shows up as exited, when I use the various macros. I have no idea how to approach this differently and would appreciate some guidance.
(i didn't include the declarations of the variables since the editor on this website was messing it up for some reason)
do{
cout << "# ";
getline(cin, input);
if (input == "jobs")
{
cout << "Process ID | State | Command " << endl;
cout << "-----------+--------------+-----------------------------------------------" << endl;
//jobs stuff goes here, need to print pids, states, and commands
if(counter == 0)
{
cout << " [NO PROCESSES] " << endl;
}
else
{
for(i = 0; i < counter; i++)
{
cout << pidArray[i] << " ";
cout << statusArray[i] << " ";
cout << cmdArray[i] << endl;
}
}
}
else
{
cmdArray[i] = input;
i++;
counter++;
pid = fork();
if( pid == 0)
{
execl("/bin/sh", "sh", "-c", input.c_str(), (char *)0);
//break;
}
else if (pid == -1)
{
break;
}
else
{
pidArray[i-1] = pid;
//int rc = waitid(P_PID, pid, NULL, WNOHANG);
// int rc =waitpid(pid, &status, WNOHANG | WNOWAIT );
//exitChecker = waitpid(pid, &status, WNOHANG);
usleep(100000);
if (WIFEXITED(status))
{
cout << "terminated" << endl;
}
else
{
cout << "running" << endl;
}
}
}
}while(input != "exit");
return 0;
}
Thanks in advance.
UPDATE: If i change async_receive_from to receive_from then there will not be any problems with rebinding. Somehow async... causes that. Previously i had one thread for every socket(with receive_from), but i had to make it work in one thread as too many threads are spawned during programm runs.
Socket is closed (i have checked), but rebinding to it causes an error. Here is an example:
#include "stdafx.h"
#include "Mmsystem.h"// for accurate timers
#pragma comment (lib,"Winmm.lib")// for accurate timers
using namespace std;
typedef shared_ptr<boost::asio::ip::udp::socket> SHP_Socket;
boost::asio::io_service io_service_;
vector<int> ports;
vector<SHP_Socket> vecSock;
vector<boost::asio::ip::udp::endpoint> vecEndpoint;
vector<boost::shared_ptr<boost::thread>> receive_threads;
bool process_all_finishing;
uint8_t Data[8000];
void receive_h(boost::system::error_code ec, size_t szPack, int i)
{
if (process_all_finishing == false)
{
cout << "\n" << i;
string f = boost::to_string(Data);
int sz = f.size();
if (sz > 12)
{
vector<int> a;
for (int i = 0; i < 100; ++i)
a.push_back(i);
a.clear();
}
}
}
void Run_io()
{
while (process_all_finishing == false)
{
io_service_.run_one();
}
cout << "\nRun_io finished";
}
void receive()
{
while (process_all_finishing == false)
{
this_thread::sleep_for(chrono::milliseconds(1));
for (unsigned i = 0; i < vecSock.size(); ++i)
{
vecSock[i]->async_receive_from(boost::asio::buffer(Data, 8000), vecEndpoint[i], boost::bind(receive_h,_1,_2,i));
}
}
cout << "\nreceive finished";
}
int main()
{
timeBeginPeriod(1);
setlocale(LC_ALL, "Russian");
try
{
ports.push_back(29005);
ports.push_back(29007);
ports.push_back(29009);
ports.push_back(29001);
vecSock.resize(3);
vecEndpoint.resize(3);
for (int i = 0; i < 3; ++i)
{
vecSock[i].reset(new boost::asio::ip::udp::socket(io_service_, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), ports[i])));
}
boost::shared_ptr<boost::thread> thread_re(new boost::thread(receive));
boost::shared_ptr<boost::thread> thread_io(new boost::thread(Run_io));
receive_threads.push_back(thread_re);
receive_threads.push_back(thread_io);
cout << "\nvecSock=3 created, giving it to work for 1 second:";
this_thread::sleep_for(chrono::seconds(1));
process_all_finishing = true;
cout << "\nSent flag to stop threads and wait for threads to finish for 1 second";
this_thread::sleep_for(chrono::seconds(1));
for (int i = 0; i < vecSock.size(); ++i)
{
cout << "\nSocket " << i << " opened =\t" << vecSock[i]->is_open();
vecSock[i]->cancel();
vecSock[i]->close();
cout << "\nSocket " << i << " counter =\t" << vecSock[i].use_count();
cout << "\nSocket " << i << " opened =\t" << vecSock[i]->is_open();
vecSock[i].reset();
cout << "\nSocket " << i << " counter =\t" << vecSock[i].use_count();
cout << "\n";
}
this_thread::sleep_for(chrono::seconds(1));
vecSock.clear();
vecSock.resize(4);
vecEndpoint.resize(4);
for (int i = 0; i < 4; ++i)
{
vecSock[i].reset(new boost::asio::ip::udp::socket(io_service_, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), ports[i])));
}
cout << "\nvecSock=4 created";
}
catch (boost::exception& e)
{
cerr <<"\n\a\a"<< boost::diagnostic_information(e);
system("pause");
}
return 0;
}
This causes an binding error (exeption) which i have redirected to console with try-catch.
Throw location unknown (consider using BOOST_THROW_EXCEPTION) Dynamic
exception type: class boost::exception_detail::clone_impl > std::exception::what: bind: Usually are
allowed only one usage of each socket address (Protocol/network
address/port)
Can ony one help? I have tried all, what I could find in references c++ and boost and nothing helped this error.
I saw this example as part of the TinyThread c++ library and noticed how it is incrementing gCount on a secondary thread, and then being printed by the main thread. See test 5
/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
Copyright (c) 2010-2012 Marcus Geelnard
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <iostream>
#include <list>
#include <tinythread.h>
#include <fast_mutex.h>
using namespace std;
using namespace tthread;
// HACK: Mac OS X and early MinGW do not support thread-local storage
#if defined(__APPLE__) || (defined(__MINGW32__) && (__GNUC__ < 4))
#define NO_TLS
#endif
// Thread local storage variable
#ifndef NO_TLS
thread_local int gLocalVar;
#endif
// Mutex + global count variable
mutex gMutex;
fast_mutex gFastMutex;
int gCount;
// Condition variable
condition_variable gCond;
// Thread function: Thread ID
void ThreadIDs(void * aArg)
{
cout << " My thread id is " << this_thread::get_id() << "." << endl;
}
#ifndef NO_TLS
// Thread function: Thread-local storage
void ThreadTLS(void * aArg)
{
gLocalVar = 2;
cout << " My gLocalVar is " << gLocalVar << "." << endl;
}
#endif
// Thread function: Mutex locking
void ThreadLock(void * aArg)
{
for(int i = 0; i < 10000; ++ i)
{
lock_guard<mutex> lock(gMutex);
++ gCount;
}
}
// Thread function: Mutex locking
void ThreadLock2(void * aArg)
{
for(int i = 0; i < 10000; ++ i)
{
lock_guard<fast_mutex> lock(gFastMutex);
++ gCount;
}
}
// Thread function: Condition notifier
void ThreadCondition1(void * aArg)
{
lock_guard<mutex> lock(gMutex);
-- gCount;
gCond.notify_all();
}
// Thread function: Condition waiter
void ThreadCondition2(void * aArg)
{
cout << " Wating..." << flush;
lock_guard<mutex> lock(gMutex);
while(gCount > 0)
{
cout << "." << flush;
gCond.wait(gMutex);
}
cout << "." << endl;
}
// Thread function: Yield
void ThreadYield(void * aArg)
{
// Yield...
this_thread::yield();
}
// Thread function: Detach
void ThreadDetach(void * aArg)
{
// We don't do anything much, just sleep a little...
this_thread::sleep_for(chrono::milliseconds(100));
}
// This is the main program (i.e. the main thread)
int main()
{
// Test 1: Show number of CPU cores in the system
cout << "PART I: Info" << endl;
cout << " Number of processor cores: " << thread::hardware_concurrency() << endl;
// Test 2: thread IDs
cout << endl << "PART II: Thread IDs" << endl;
{
// Show the main thread ID
cout << " Main thread id is " << this_thread::get_id() << "." << endl;
// Start a bunch of child threads - only run a single thread at a time
thread t1(ThreadIDs, 0);
t1.join();
thread t2(ThreadIDs, 0);
t2.join();
thread t3(ThreadIDs, 0);
t3.join();
thread t4(ThreadIDs, 0);
t4.join();
}
// Test 3: thread local storage
cout << endl << "PART III: Thread local storage" << endl;
#ifndef NO_TLS
{
// Clear the TLS variable (it should keep this value after all threads are
// finished).
gLocalVar = 1;
cout << " Main gLocalVar is " << gLocalVar << "." << endl;
// Start a child thread that modifies gLocalVar
thread t1(ThreadTLS, 0);
t1.join();
// Check if the TLS variable has changed
if(gLocalVar == 1)
cout << " Main gLocalID was not changed by the child thread - OK!" << endl;
else
cout << " Main gLocalID was changed by the child thread - FAIL!" << endl;
}
#else
cout << " TLS is not supported on this platform..." << endl;
#endif
// Test 4: mutex locking
cout << endl << "PART IV: Mutex locking (100 threads x 10000 iterations)" << endl;
{
// Clear the global counter.
gCount = 0;
// Start a bunch of child threads
list<thread *> threadList;
for(int i = 0; i < 100; ++ i)
threadList.push_back(new thread(ThreadLock, 0));
// Wait for the threads to finish
list<thread *>::iterator it;
for(it = threadList.begin(); it != threadList.end(); ++ it)
{
thread * t = *it;
t->join();
delete t;
}
// Check the global count
cout << " gCount = " << gCount << endl;
}
// Test 5: fast_mutex locking
cout << endl << "PART V: Fast mutex locking (100 threads x 10000 iterations)" << endl;
{
// Clear the global counter.
gCount = 0;
// Start a bunch of child threads
list<thread *> threadList;
for(int i = 0; i < 100; ++ i)
threadList.push_back(new thread(ThreadLock2, 0));
// Wait for the threads to finish
list<thread *>::iterator it;
for(it = threadList.begin(); it != threadList.end(); ++ it)
{
thread * t = *it;
t->join();
delete t;
}
// Check the global count
cout << " gCount = " << gCount << endl;
}
// Test 6: condition variable
cout << endl << "PART VI: Condition variable (40 + 1 threads)" << endl;
{
// Set the global counter to the number of threads to run.
gCount = 40;
// Start the waiting thread (it will wait for gCount to reach zero).
thread t1(ThreadCondition2, 0);
// Start a bunch of child threads (these will decrease gCount by 1 when they
// finish)
list<thread *> threadList;
for(int i = 0; i < 40; ++ i)
threadList.push_back(new thread(ThreadCondition1, 0));
// Wait for the waiting thread to finish
t1.join();
// Wait for the other threads to finish
list<thread *>::iterator it;
for(it = threadList.begin(); it != threadList.end(); ++ it)
{
thread * t = *it;
t->join();
delete t;
}
}
// Test 7: yield
cout << endl << "PART VII: Yield (40 + 1 threads)" << endl;
{
// Start a bunch of child threads
list<thread *> threadList;
for(int i = 0; i < 40; ++ i)
threadList.push_back(new thread(ThreadYield, 0));
// Yield...
this_thread::yield();
// Wait for the threads to finish
list<thread *>::iterator it;
for(it = threadList.begin(); it != threadList.end(); ++ it)
{
thread * t = *it;
t->join();
delete t;
}
}
// Test 8: sleep
cout << endl << "PART VIII: Sleep (10 x 100 ms)" << endl;
{
// Sleep...
cout << " Sleeping" << flush;
for(int i = 0; i < 10; ++ i)
{
this_thread::sleep_for(chrono::milliseconds(100));
cout << "." << flush;
}
cout << endl;
}
// Test 9: detach
cout << endl << "PART IX: Detach" << endl;
{
thread t(ThreadDetach, 0);
t.detach();
cout << " Detached from thread." << endl;
}
}
So I tried to make my own code, but not only does the main thread not see the variable increment, but when I added sleep to the worker thread it no longer tries to print the variable on the main thread. Because of these two problems the worker thread never quits either.
#include <iostream>
#include <list>
#include "tinythread.h"
#include "fast_mutex.h"
using namespace std;
using namespace tthread;
fast_mutex workerThreadMutex;
bool killThread = false;
int number = 0;
void workerThread(void * aArg)
{
bool running = true;
int number = 0;
while(running)
{
lock_guard<fast_mutex> lock(workerThreadMutex);
number++;
cout << "secondThread::" << number << endl;
this_thread::sleep_for(chrono::milliseconds(1000));
if(killThread)
running =true;
}
}
int main()
{
thread* wThread = new thread(workerThread, 0);
bool running = true;
while(running)
{
this_thread::sleep_for(chrono::milliseconds(100));
if(workerThreadMutex.try_lock())
{
cout << "mainThread::" << number << endl;
if(number == 100)
{
killThread = true;
running = false;
}
workerThreadMutex.unlock();
}
}
wThread->join();
delete wThread;
return 0;
}
Can you help?
edit: made a change to my code
edit: fixed local variable issue, it works now, except for the kill thread boolean is not being detected so the secondary thread (worker thread) is not exiting.
edit: fixed issue with local variable
edit: fixed issue with sleep
edit: fixed issue killThread
edit: all problems fixed
#include <iostream>
#include <list>
#include "tinythread.h"
#include "fast_mutex.h"
using namespace std;
using namespace tthread;
fast_mutex workerThreadMutex;
bool killThread = false;
int number = 0;
bool running = true;
void workerThread(void * aArg)
{
while(running)
{
{
lock_guard<fast_mutex> lock(workerThreadMutex);
number++;
if(killThread)
running =false;
}
this_thread::sleep_for(chrono::milliseconds(50));
}
}
int main()
{
thread* wThread = new thread(workerThread, 0);
while(running)
{
this_thread::sleep_for(chrono::milliseconds(100));
if(workerThreadMutex.try_lock())
{
cout << "mainThread::" << number << endl;
if(number > 100)
{
killThread = true;
//running = false;
}
workerThreadMutex.unlock();
}
}
wThread->join();
delete wThread;
return 0;
}
edit: further modification to show portable c++11 friendly inter thread communication
#include <iostream>
#include <sstream>
#include "tinythread.h"
#include "fast_mutex.h"
using namespace std;
using namespace tthread;
fast_mutex workerThreadMutex;
bool killThread = false;
int number = 0;
bool running = true;
string message = "";
void workerThread(void * aArg)
{
while(running)
{
{
lock_guard<fast_mutex> lock(workerThreadMutex);
if(message=="")
{
number++;
ostringstream Convert;
Convert << number;
message = Convert.str();
}
if(killThread)
running =false;
}
this_thread::sleep_for(chrono::milliseconds(1));
}
}
int main()
{
thread* wThread = new thread(workerThread, 0);
bool stopMainThreadLoop = false;
while(!stopMainThreadLoop)
{
this_thread::sleep_for(chrono::milliseconds(10));
if(workerThreadMutex.try_lock())
{
//cout << "mainThread::" << number << endl;
cout << "mainThread::" << message << endl;
//if(number > 100)
if(message == "100")
{
killThread = true;
stopMainThreadLoop = true;
}
message = "";
workerThreadMutex.unlock();
}
}
wThread->join();
delete wThread;
return 0;
}
Look at this part of your code
int number = 0; // Global variable, i.e. will be used by main
void workerThread(void * aArg)
{
bool running = true;
int number = 0; // Local variable, i.e. will be used by in the function
So mainis using one variable and the function (aka the thread) is using another. Consequently main can't see any increments.
Just remove the local variable.
For the sleep part
I think the problem is that you do the sleep while holding the mutex.
Try this:
void workerThread(void * aArg)
{
bool running = true;
//---------------------- int number = 0;
while(running)
{
{
lock_guard<fast_mutex> lock(workerThreadMutex);
number++;
//cout << "secondThread::" << number << endl;
if(killThread)
running =true;
}
this_thread::sleep_for(chrono::milliseconds(1000));
}
}
For the kill:
Try this
if(number >= 100) // Changed
{
killThread = true;
running = false;
}
Inside the function
if(killThread)
running =true; // Should be false
I want to fork three child process in one parent.
And the following is my C++ code:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;
int main()
{
pid_t pid;
for (int i = 0; i < 3; i++)
{
pid = fork();
if (pid < 0)
{
cout << "Fork Error";
return -1;
}
else if (pid == 0)
cout << "Child " << getpid() << endl;
else
{
wait(NULL);
cout << "Parent " << getpid() << endl;
return 0;
}
}
}
Now my output is :
Child 27463
Child 27464
Child 27465
Parent 27464
Parent 27463
Parent 27462
How should I modify my program to get the output like the following?
Child 27463
Child 27464
Child 27465
Parent 27462
What I mean is that these THREE children need to belong to the same ONE parent, can anybody give me some suggestion ?
Thank you all. :)
You should exit the execution of the child processes. Otherwise, they continue forking also
pid_t pid;
for(i = 0; i < 3; i++) {
pid = fork();
if(pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
cout << "Child " << getpid() << endl;
exit(0);
} else {
wait(NULL);
cout << "Parent " << getpid() << endl;
}
}
There are two issues:
children zero and one continue with the for loop, spawning further processes;
the "parent" branch terminates instead of continuing with the loop.
The following will produce the output you want:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;
int main()
{
pid_t pid;
for (int i = 0; i < 3; i++)
{
pid = fork();
if (pid < 0)
{
cout << "Fork Error";
return -1;
}
else if (pid == 0) {
cout << "Child " << getpid() << endl;
return 0;
} else {
wait(NULL);
if (i == 2) {
cout << "Parent " << getpid() << endl;
}
}
}
}
When I run it, I get
Child 4490
Child 4491
Child 4492
Parent 4489
Move your return 0 from the last condition to the middle one:
if (pid < 0)
{
cout << "Fork Error";
return -1;
}
else if (pid == 0) {
cout << "Child " << getpid() << endl;
return 0;
}
else
{
wait(NULL);
cout << "Parent " << getpid() << endl;
}
This way the parent will continue to loop, and the children will terminate instead of looping.