Using pipes to communicate with children in multithreaded programs - c++

I am trying to use fork to execute child programs from a multithreaded parent using code similar to:
#include <thread>
#include <unistd.h>
#include <vector>
#include <sys/wait.h>
void printWithCat(const std::string& data) {
std::vector<char*> commandLine;
// exec won't change argument so safe cast
commandLine.push_back(const_cast<char*>("cat"));
commandLine.push_back(0);
int pipes[2];
pipe(pipes);
// Race condition here
pid_t pid = fork();
if (pid == 0) {
// Redirect pipes[0] to stdin
close(pipes[1]);
close(0);
dup(pipes[0]);
close(pipes[0]);
execvp("cat", &commandLine.front());
}
else {
close(pipes[0]);
write(pipes[1], (void*)(data.data()), data.size());
close(pipes[1]);
waitpid(pid, NULL, 0);
}
}
int main()
{
std::thread t1(printWithCat, "Hello, ");
std::thread t2(printWithCat, "World!");
t1.join();
t2.join();
}
This code contains a race condition between the call to pipe and the call to fork. If both threads create pipes and then fork, each child process contains open file descriptors to both pipes and only close one. The result is that a pipe never gets closed and the child process never exits. I currently wrap the pipe and fork calls in a global lock but this adds an additional synchronisation. Is there a better way?

Don't think you're avoiding synchronization by avoiding a lock in your code -- the kernel is going to take locks for process creation anyway, probably on a far more global level than your lock.
So go ahead and use a lightweight mutex here.
Your problems are going to arise when different parts of the program make fork calls and don't agree on a single mutex (because some are buried in library code, etc)

Related

OS Signal handling loop - blocking or non-blocking read?

My application has a thread for handling OS signals, so to not block the programLoop(). This thread, processOSSignals, basically keeps on reading the file descriptor for signals SIGINT, SIGTERM, SIGQUIT. On their reception, loopOver being initially true, is set to false.
int mSigDesc = -1;
void init()
{
// creates file descriptor for reading SIGINT, SIGTERM, SIGQUIT
// blocks signals with sigprocmask(SIG_BLOCK, &mask, nullptr)
...
mSigDesc = signalfd(mSigDesc, &mask, SFD_NONBLOCK); // OR 3rd param = 0?
}
void processOSSignals()
{
while (loopOver)
{
struct signalfd_siginfo fdsi;
auto readedBytes = read(mSigDesc, &fdsi, sizeof(fdsi));
...
}
}
int main()
{
init();
std::thread ossThread(processOSSignals);
programLoop();
ossThread.join();
}
My question is - should mSigDesc be set to blocking or non-blocking (asynchronous) mode?
In non-blocking mode, this thread is always busy, but inefficiently reading and returning EAGAIN over and over again.
In blocking mode, it waits until one of the signals is received, but if it is never sent, the ossThread will never join.
How should it be handled? Use sleep() in the non-blocking mode, to attempt reading only occasionally? Or maybe use select() in the blocking mode, to monitor mSigDesc and read only when sth. is available there?
Whether you use blocking or non-blocking I/O depends on how you want to handle your I/O.
Typically, if you have a single thread which is dedicated to reading from the signal file descriptor and you simply want it to wait until it gets a signal, then you should use blocking I/O.
However, in many contexts, spawning a single thread for each I/O operation is inefficient. A thread requires a stack, which may consume a couple megabytes, and it's often more efficient to process many file descriptors (which may be of many different types) by putting them all in non-blocking mode and waiting until one of them is ready.
Typically, this is done portably using poll(2). select(2) is possible, but on many systems, it is limited to a certain number of file descriptors (on Linux, 1024), and many programs will exceed that number. On Linux, the epoll(7) family of functions can also be used, and you may prefer that if you're already using such non-portable constructions as signalfd(2).
For example, you might want to handle signal FDs as part of your main loop, in which case including that FD as one the FDs that your main loop processes using poll(2) or one of the other functions might be more desirable.
What you should avoid doing is spinning in a loop or sleeping with a non-blocking socket. If you use poll(2), you can specify a timeout after which the operation returns 0 if no file descriptor was ready, so you can already control a timeout without needing to resort to sleep.
Same advise as bk2204 outlined: Just use poll. If you want to have a separate thread, a simple way to signal that thread is to add the read side of a pipe (or socket) to the set of polled file descriptors. The main thread then closes the write side when it wants the thread to stop. poll will then return and signal that reading from the pipe is possible (since it will signal EOF).
Here is the outline of an implementation:
We start by defining an RAII class for file descriptors.
#include <unistd.h>
// using pipe, close
#include <utility>
// using std::swap, std::exchange
struct FileHandle
{
int fd;
constexpr FileHandle(int fd=-1) noexcept
: fd(fd)
{}
FileHandle(FileHandle&& o) noexcept
: fd(std::exchange(o.fd, -1))
{}
~FileHandle()
{
if(fd >= 0)
::close(fd);
}
void swap(FileHandle& o) noexcept
{
using std::swap;
swap(fd, o.fd);
}
FileHandle& operator=(FileHandle&& o) noexcept
{
FileHandle tmp = std::move(o);
swap(tmp);
return *this;
}
operator bool() const noexcept
{ return fd >= 0; }
void reset(int fd=-1) noexcept
{ *this = FileHandle(fd); }
void close() noexcept
{ reset(); }
};
Then we use that to construct our pipe or socket pair.
#include <cerrno>
#include <system_error>
struct Pipe
{
FileHandle receive, send;
Pipe()
{
int fds[2];
if(pipe(fds))
throw std::system_error(errno, std::generic_category(), "pipe");
receive.reset(fds[0]);
send.reset(fds[1]);
}
};
The thread then uses poll on the receive end and its signalfd.
#include <poll.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <cassert>
void processOSSignals(const FileHandle& stop)
{
sigset_t mask;
sigemptyset(&mask);
FileHandle sighandle{ signalfd(-1, &mask, 0) };
if(! sighandle)
throw std::system_error(errno, std::generic_category(), "signalfd");
struct pollfd fds[2];
fds[0].fd = sighandle.fd;
fds[1].fd = stop.fd;
fds[0].events = fds[1].events = POLLIN;
while(true) {
if(poll(fds, 2, -1) < 0)
throw std::system_error(errno, std::generic_category(), "poll");
if(fds[1].revents & POLLIN) // stop signalled
break;
struct signalfd_siginfo fdsi;
// will not block
assert(fds[0].revents != 0);
auto readedBytes = read(sighandle.fd, &fdsi, sizeof(fdsi));
}
}
All that remains to be done is create our various RAII classes in such an order that the write side of the pipe is closed before the thread is joined.
#include <thread>
int main()
{
std::thread ossThread;
Pipe stop; // declare after thread so it is destroyed first
ossThread = std::thread(processOSSignals, std::move(stop.receive));
programLoop();
stop.send.close(); // also handled by destructor
ossThread.join();
}
Other things to note:
Consider switching to std::jthread so that it joins automatically even if the program loop throws an exception
Depending on what your background thread does, you can also simply abandon it on program end by calling std::thread::detach
If the thread may stay busy (not calling poll) for long loops, you can pair the pipe up with an std::atomic<bool> or jthread's std::stop_token to signal the stop event. That way the thread can check the flag in between loop iterations. Incidentally, your use of a plain global int was invalid as you read and write from different threads at the same time
You could also use the signalfd and send a specific signal to the thread for it to quit

C++ What possible ways can a detached thread signal it is terminating?

I had three initial ideas about this
Firstly some kind of counter? (Maybe using mutex?)
Some kind of semophore? (I don't know much about these) OR perhaps a promise/future combination
Some other kind of signal/slot mechanism, similar to that of the signal created by CTRL-C (SIGINT etc)
I'm working on some software which makes use of detached threads to do some work. Unfortunatly the threads don't clean up nicely, they just quit at the end of execution. This is fine for communication in one direction (ie; main() can quit first), but won't work the other way around - at the moment there is no way for main() to know when the threads have finished working and to exit gracefully.
To expand on those bullet points...
My initial idea was to have a protected region of variables - could be a counter or an array of flags, one for each thread, and to access these using a mutex. The mutex might not even be necessary if using one variable per detached thread to signal the end of the thread working, because main() will "poll" these variables, which is a read-only operation. Only the detached threads themselves need write access. If more than one detached thread uses the same counter/variable then a mutex would be required.
The next idea I had was to use a semophore (which is something I really know nothing about) or promise/future combinations, which I think would work as a possible option.
The final thought was some kind of signals mechanism, like possibly "stealing" a SIGxyz signal (like SIGINT) and using that to some how communicate the end of a thread execution. I'm not confident about this one however.
My question is really - how is this supposed to be done? What would the typical engineering solution to this problem be?
(Final thought: Using a file, or a pipe? Seems a bit complicated though?)
Perhaps I overlooked the question but I think you could use an atomic variable as a flag in order to notify the detached thread's termination.
Something like the following example:
#include <thread>
#include <iostream>
#include <atomic>
int main()
{
// Define a flag to notify detached thread's termination
std::atomic_bool term_flag;
// Define some function to run concurrently
auto func = [&term_flag](){
std::this_thread::sleep_for(std::chrono::seconds(2));
term_flag = true;
};
// Run and detach the thread
term_flag = false;
std::thread t(func);
t.detach();
// Wait until detached thread termination
while(!term_flag)
std::this_thread::yield();
std::cout << "Detached Thread has terminated properly" << std::endl;
return 0;
}
Output:
Detached Thread has terminated properly
EDIT:
As Hans Passant mentioned, you could also use a condition variable associated with a mutex to do it.
This would be a better solution (but a bit less readable in my humble opinion) since we have more control over how much to wait.
The basic example above could then be rewritten as:
#include <thread>
#include <iostream>
#include <mutex>
#include <condition_variable>
int main()
{
// Define the mutex and the condition variable to notify the detached thread's termination
std::mutex m;
std::condition_variable cv;
// Define some function to run concurrently
auto func = [&cv](){
std::this_thread::sleep_for(std::chrono::seconds(2));
cv.notify_one();
};
// Run and detach the thread
std::thread t(func);
t.detach();
// Wait until detached thread termination
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk);
}
std::cout << "Detached Thread has terminated properly" << std::endl;
return 0;
}

Running two programs concurrently

I have two C++ programs built in Ubuntu, and I want to run them concurrently. I do not want to combine them into one C++ project and run each on a different thread, as this is causing me all sorts of problems.
The solution I effectively want to emulate, is when I open two tabs in the terminal, and run each program in a separate tab. However, I also want one program (let's call this Program A) to be able to quit and rerun the other program (Program B). This cannot be achieved just in the terminal.
So what I want to do is to write some C++ code in Program A, which can run and quit Program B at any point. Both programs must run concurrently, so that Program A doesn't have to wait until Program B returns before continuing on with Program A.
Any ideas? Thanks!
In Linux you can fork the current process, which creates a new process.
Then you have to launch the new process with some exec system call.
Refer to:
http://man7.org/linux/man-pages/man2/execve.2.html
For example:
#include <unistd.h> /* for fork */
#include <sys/types.h> /* for pid_t */
#include <sys/wait.h> /* for wait */
int main(int argc,char** argv)
{
pid_t pid=fork();
if (pid==0)
{
execv("/bin/echo",argv);
}
}
You have multiple options here:
The traditional POSIX fork / exec (there are literally tons of examples on how to do this in SO, for example this one).
If you can use Boost then Boost process is an option.
If you can use Qt then QProcess is an option.
Boost and Qt also provide nice means manipulating the standard input/output of the child process if this is important. If not the classical POSIX means should do fine.
Take a look at the Linux operating system calls, fork() and exec(). The fork() call will create two copies of the current process which continue to execute simultaneously.
In the parent process, fork()'s return value is the PID (process ID) of
the child process.
In the child process, fork()'s return value is 0.
On error, fork()'s return value is -1.
You can use this to your advantage to control the behavior of the parent and child. As an example:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
int main(int argc,char** argv)
{
char* progB = "/bin/progB";
char* args[progName, "arg1", "arg2", ..., NULL];
char* env[NULL]; // can fill in environment here.
pid_t pid=fork();
if (pid==0)
{
// In child...
execv(progB, args, env);
}
else if (pid == -1)
{
// handle error...
}
else
{
// In parent; pid is the child process.
// can wait for child or kill child here.
}
}
To wait until your child exits (in the third case above), you can use wait(2), which returns your child pid on successful termination or -1 on error:
pid_t result = waitpid(pid, &status, options);
To kill your child preemptively, you can send a kill signal as described in kill(2):
int result = kill(pid, SIGKILL); // or whatever signal you wish
This should allow you to manage your processes as described in the original question.

C++ thread still alive after kill?

I have an issue: I create a thread to execute a command line and sometimes it takes a lot of time for waiting. So, I want to kill this thread and I implement below code:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
using namespace std;
void* doSomeThing(void *)
{
cout<<"Begin execute"<<endl;
system("svn info http://wrong_link_it's_take_a_lot_of_time_to_execute");
return NULL;
}
int main() {
pthread_t myThread;
int err = pthread_create(&myThread,NULL, &doSomeThing,NULL);
if(err != 0)
{
cout<<"Create thread not success"<<endl;
}
sleep(2);
if(pthread_cancel(myThread) == 0)
{
cout<<"Thread was be kill"<<endl;
}
sleep(3);
cout<<"End of program";
return 0;
}
I'm using pthread_cancel to kill this thread and the line cout<<"Thread was be kill"<<endl; always appear after I execute. It is meant this thread being killed, but I saw the surprise result when I ran it on Eclipse (both on Ubuntu and Windows 7)
Anybody can explain to me why this thread still alive after kill and can you give me some method to resolve this issue.
Thank you.
cancelling a thread is not actually killing it. it just requests cancellation:
pthread_cancel - send a cancellation request to a thread
(from man pthread_cancel).
The pthread_cancel() function sends a cancellation request to the
thread thread. Whether and when the target thread reacts to the
cancellation
request depends on two attributes that are under the control of that thread: its cancelability state and type.
As pointed out by Marcus Müller in his answer, pthread_cancel() not necessarily ends the thread addressed.
Do not use system() if you want to kill what had been run.
Create your own new child process using fork()/exec*().
If it's time to end the child let the parent issue a kill() on the PID returned by fork()ing in 1.

Thread ending unexpectedly. c++

I'm trying to get a hold on pthreads. I see some people also have unexpected pthread behavior, but none of the questions seemed to be answered.
The following piece of code should create two threads, one which relies on the other. I read that each thread will create variables within their stack (can't be shared between threads) and using a global pointer is a way to have threads share a value. One thread should print it's current iteration, while another thread sleeps for 10 seconds. Ultimately one would expect 10 iterations. Using break points, it seems the script just dies at
while (*pointham != "cheese"){
It could also be I'm not properly utilizing code blocks debug functionality. Any pointers (har har har) would be helpful.
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include <string>
using namespace std;
string hamburger = "null";
string * pointham = &hamburger;
void *wait(void *)
{
int i {0};
while (*pointham != "cheese"){
sleep (1);
i++;
cout << "Waiting on that cheese " << i;
}
pthread_exit(NULL);
}
void *cheese(void *)
{
cout << "Bout to sleep then get that cheese";
sleep (10);
*pointham = "cheese";
pthread_exit(NULL);
}
int main()
{
pthread_t threads[2];
pthread_create(&threads[0], NULL, cheese, NULL);
pthread_create(&threads[1], NULL, wait, NULL);
return 0;
}
The problem is that you start your threads, then exit the process (thereby killing your threads). You have to wait for your threads to exit, preferably with the pthread_join function.
If you don't want to have to join all your threads, you can call pthread_exit() in the main thread instead of returning from main().
But note the BUGS section from the manpage:
Currently, there are limitations in the kernel implementation logic for
wait(2)ing on a stopped thread group with a dead thread group leader.
This can manifest in problems such as a locked terminal if a stop sig‐
nal is sent to a foreground process whose thread group leader has
already called pthread_exit().
According to this tutorial:
If main() finishes before the threads it has created, and exits with pthread_exit(), the other threads will continue to execute. Otherwise, they will be automatically terminated when main() finishes.
So, you shouldn't end the main function with the statement return 0;. But you should use pthread_exit(NULL); instead.
If this doesn't work with you, you may need to learn about joining threads here.