I'm having trouble instituting a timeout in one of my pthreads. I've simplified my code here and I've isolated the issue to be the CNF algorithm I'm running in the thread.
int main(){
pthread_t t1;
pthread_t t2;
pthread_t t3; //Running multiple threads, the others work fine and do not require a timeout.
pthread_create(&t1, nullptr, thread1, &args);
pthread_join(t1, nullptr);
std::cout << "Thread should exit and print this\n"; //This line never prints since from what I've figured to be a lack of cancellation points in the actual function running in the thread.
return 0;
}
void* to(void* args) {
int timeout{120};
int count{0};
while(count < timeout){
sleep(1);
count++;
}
std::cout << "Killing main thread" << std::endl;
pthread_cancel(*(pthread_t *)args);
}
void *thread1 (void *arguments){
//Create the timeout thread within the CNF thread to wait 2 minutes and then exit this whole thread
pthread_t time;
pthread_t cnf = pthread_self();
pthread_create(&time, nullptr, &timeout, &cnf);
//This part runs and prints that the thread has started
std::cout << "CNF running\n";
auto *args = (struct thread_args *) arguments;
int start = args->vertices;
int end = 1;
while (start >= end) {
//This is where the issue lies
cover = find_vertex_cover(args->vertices, start, args->edges_a, args->edges_b);
start--;
}
pthread_cancel(time); //If the algorithm executes in the required time then the timeout is not needed and that thread is cancelled.
std::cout << "CNF END\n";
return nullptr;
}
I tried commenting out the find_vertex_cover function and add an infinite loop and I was able to create a timeout and end the thread that way. The function is actually working the exact way it should. It should take forever to run under the conditions I'm running it at and therefore I need a timeout.
//This was a test thread function that I used to validate that implementing the timeout using `pthread_cancel()` this way works. The thread will exit once the timeout is reached.
void *thread1 (void *args) {
pthread_t x1;
pthread_t x2 = pthread_self();
pthread_create(&x1, nullptr, to, &x2);
/*
for (int i = 0;i<100; i++){
sleep(1);
std::cout << i << std::endl;
}
*/
}
Using this function I was able to validate that my timeout thread approach worked. The issue is when I actually run the CNF algorithm (using Minisat under the hood) once find_vertex_cover runs, there is no way to end the thread. The algorithm is expected to fail in the situation I'm implementing which is why a timeout is being implemented.
I've read up on using pthread_cancel() and while it isn't a great way it's the only way I could implement a timeout.
Any help on this issue would be appreciated.
I've read up on using pthread_cancel() and while it isn't a great way [..]
That's right. pthread_cancel should be avoided. It's especially bad for use in C++ as it's incompatible with exception handling. You should use std::thread and for thread termination, you can possibly use conditional variable or a atomic variable that terminates the "infinite loop" when set.
That aside, cancellation via pthread_cancel depends on two things: 1) cancellation state 2) cancellation type.
Default cancellation state is enabled. But the default cancellation type is deferred - meaning the cancellation request will be delivered only at the next cancellation point. I suspect there's any cancellation points in find_vertex_cover. So you could set the cancellation type to asynchronous via the call:
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
from the thread(s) you want to be able to cancel immediately.
But again, I suggest to not go for pthread_cancel approach at all and instead rewrite the "cancel" logic so that it doesn't involve pthread_cancel.
Related
I want to write a program in which many functions run simultaneously. I already figured out that in order to do that I need to use threads.
In my program a routine of heating and rotating an object with different temperatures and velocities has to run for a determined period of time in a loop. Once the time has passed I want the process to continue with my next heating/rotating (...). My idea was to write a "timer thread" that is able to end the current routine in some way, and skip to the next one. Is this possible?
I suppose most ways to do this are going to involve a shared flag between the working thread and the thread that signals it to stop working.
So you might have something along these lines:
// Use a std::atomic_bool to signal the thread safely
void process_stuff(std::atomic_bool& stop_processing)
{
while(!stop_processing) // do we keep going?
{
// do some measurements or action
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // wait for next action
}
}
Elsewhere in another thread ...
std::atomic_bool stop_processing{false};
// start thread (use std::ref() to pass by reference)
std::thread proc_thread(process_stuff, std::ref(stop_processing));
// wait for some time...
std::this_thread::sleep_for(std::chrono::seconds(3));
stop_processing = true; // signal end
proc_thread.join(); // wait for end to happen
// now create a new thread...
In the initiating thread, by changing the value of the variable stop_processing you signal the running thread to stop looping, in which case it ends gracefully.
Check this:
int main() {
// first thread
auto thread1 = std::make_unique<std::thread>([]() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "over\n";
});
// disposing to second thread
std::thread([thread2 = std::move(thread1)](){
thread2->join();
}).detach();
//spinning a new thread
thread1.reset(new std::thread([]() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "next over\n";
}));
thread1->join();
return 0;
}
I am learning multi-threading in Linux platform. I wrote this small program to get comfort with the concepts. On running the executable, I could not see any error nor does it print Hi. Hence I made to sleep the thread after I saw the output. But still could not see the prints on the console.
I also want to know which thread prints at run time. Can anyone help me?
#include <iostream>
#include <unistd.h>
#include <pthread.h>
using std::cout;
using std::endl;
void* print (void* data)
{
cout << "Hi" << endl;
sleep(10000000);
}
int main (int argc, char* argv[])
{
int t1 = 1, t2 =2, t3 = 3;
pthread_t thread1, thread2, thread3;
int thread_id_1, thread_id_2, thread_id_3;
thread_id_1 = pthread_create(&thread1, NULL, print, 0);
thread_id_2 = pthread_create(&thread2, NULL, print, 0);
thread_id_3 = pthread_create(&thread3, NULL, print, 0);
return 0;
}
Your main thread probably exits and thus the entire process dies. So, the threads don't get a chance to run. It's also possible (quite unlikely but still possible) that you'd see the output from the threads even with your code as-is if the threads complete execution before main thread exits. But you can't rely on that.
Call pthread_join(), which suspends the calling thread until the thread (specified by the thread ID) returns, on the threads after the pthread_create() calls in main():
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
You can also use an array of pthread_t which would allow you to use a for loop over the pthread_create() and pthread_join() calls.
Or exit only the main thread using pthread_exit(0), which would exit only the calling thread and the remaining threads (the ones you created) will continue execution.
Note that your thread function should return a pointer or NULL:
void* print (void* data)
{
cout << "Hi" << endl;
return NULL;
}
Not sure about the high sleeps either right the threads exit, which is unnecessary and would hold the threads from exiting. Probably not something you wanted.
This is my sender thread once after it is called for first time its finish its execution. I Couldn't be able to resume this sender thread. Is There any mechanism in C++ to resume threads.
void ClientSocket::sender()
{
char buf[1024];
//readBuffer = m_ptrsendStream->Read_Adt(filePath);
//readStream();
//cout << readBuffer.str()<<endl;
cout << "write stream to send through socket\n" << endl;
cin >> buf;
if (isConnected == 0)
{
//send(clientSock, readBuffer.str().c_str(), strlen((char *)readBuffer.str().c_str()), 0);
send(clientSock, buf, strlen(buf), 0);
cout << "sending stream :\n"<<endl << buf << endl;
}
}
//this is where my thread creation happens and join() happens.
int main(int argc, char *argv[])
{
ClientSocket objSocket(argv[1]);
sender_thread = make_shared<thread>([&objSocket]() {
objSocket.sender();
});
try
{
if (sender_thread->joinable())
sender_thread->join();
}
No, once your thread has joined it's done and you need to create a new one.
If you have this pattern where you are constantly creating new threads it might be worthwhile to think about using a threadpool to avoid the overhead of constantly spawning new threads.
In addition, if this is related to networking it's probably best to avoid using threads and instead use something asynchronous like boost::asio.
Terminated threads cannot be resumed (this is not a C++ limitation, but a general limitation; when speaking about resuming thread, it is usually about resuming after previously suspending it).
After join() has returned, corresponding thread is already terminated; it has no state (except maybe for zobmie stuff and return code, but this is of no use for your purposes), and there is nothing to resume
However, it is possible to run your sender() function in another thread, just create another instance of your thread.
EDIT: I concur with #inf on using asio instead of threads whenever possible.
You want resume thread which is completed , normally thread resume used continue from suspended threads . Instead of resuming the thread ,stop come of thread un till it finish all actions , make use of while or wait in thread .
I am writing a simple client-server application using pthread-s API, which in pseudo code
looks something like this:
static volatile sig_atomic_t g_running = 1;
static volatile sig_atomic_t g_threads = 0;
static pthread_mutex_t g_threads_mutex;
static void signalHandler(int signal)
{
g_running = 0;
}
static void *threadServe(void *params)
{
/* Increment the number of currently running threads. */
pthread_mutex_lock(&g_threads_mutex);
g_threads++;
pthread_mutex_unlock(&g_threads_mutex);
/* handle client's request */
/* decrement the number of running threads */
pthread_mutex_lock(&g_threads_mutex);
g_threads--;
pthread_mutex_unlock(&g_threads_mutex);
}
int main(int argc, char *argv[])
{
/* do all the initialisation
(set up signal handlers, listening socket, ... ) */
/* run the server loop */
while (g_running)
{
int comm_sock = accept(listen_socket, NULL, 0);
pthread_create(&thread_id, NULL, &threadServe, comm_sock) ;
pthread_detach(thread_id);
}
/* wait for all threads that are yet busy processing client requests */
while (1)
{
std::cerr << "Waiting for all threads to finish" << std::endl;;
pthread_mutex_lock(&g_threads_mutex);
if (g_threads <= 0)
{
pthread_mutex_unlock(&g_threads_mutex);
break;
}
pthread_mutex_unlock(&g_threads_mutex);
}
/* clean up */
}
So the server is running in an infinite loop until a signal (SIGINT or SIGTERM) is received. The purpose of the second while loop is to let all the threads (that were processing client requests at the time a signal was received) to have a chance to finish the work they already started.
However I don't like this design very much, because that second while loop is basically a busy loop wasting cpu resources.
I tried to search on Google for some good examples on threaded concurrent server, but I had no luck. An idea that came to my mind was to use pthread_cond_wait() istead of that loop, but I am not sure if this does not bring further problems.
So the question is, how to improve my design, or point me to a nice simple example that deals with similar problem as mine.
EDIT:
I was considering pthread_join(), but I din't know how to join with worker thread,
while the main server loop (with accept() call in it) would be still running.
If I called pthread_join() somewhere after pthread_create()
(instead of pthread_detach()), then the while loop would be blocked until the worker
thread is done and the whole threading would not make sense.
I could use pthread_join() if I spawned all the threads at program start,
but then I would have them around for the entire life of my server,
which I thought might be a little inefficient.
Also after reading man page I understood, that pthread_detach() is exactly
suitable for this purpose.
The busy loop slurping CPU can easily be altered by having a usleep(10000); or something like that outside your mutex lock.
It would be more light-weight if you use a std::atomic<int> g_threads; - that way, you could get rid of the mutex altogether.
If you have an array of (active) thread_id's, you could just use a loop of
for(i = 0; i < num_active_threads; i++)
pthread_join(arr[i]);
I'm trying to make a multiclient server. I have this thread:
void client_thread(int new_socket)
{
int size;
char inbuffer[BUF];
do
{
cout << "Waiting for messages: " << endl;
size = recv(new_socket, inbuffer, BUF, 0);
} while (true);
}
and this main procedure:
int main()
{
while (true)
{
//waiting for clients
cout << "Waiting for connections..." << endl;
new_socket = accept ( create_socket, (struct sockaddr *) &cliaddress, &addrlen );
//new client connected
if (new_socket > 0)
{
//start thread
thread(client_thread, new_socket).join();
}
}
return 0;
}
When the first client connects, the thread starts and the server is waiting for messages from him. But the server doesn't wait for new clients anymore. I don't know why. Is it because of the infinite do-while loop inside the thread-function? What's the point of threads if they block your whole program if they contain infinite loops?
The main routine blocks, because it waits for the thread to finish: join().
If you don't want to block, then don't join() your client_thread.
This exception might come from the destruction of your anonymous thread object. When you leave the scope of if() all objects in this scope are destroyed. From http://en.cppreference.com/w/cpp/thread/thread/~thread you can see, the destructor calls terminate(). To avoid it, you can call detach(). So instead of thread(client_thread, new_socket).join();, you must say thread(client_thread, new_socket).detach();.
You are supposed to create a thread and keep a reference to it until you joined it. In your code, the thread object is deallocated right after being created, hence your error if don't call join immediately.
To achieve this properly, the best way is to allocate the object on the heap, using the operator new and store the pointer in a list somewhere. When the thread is done it may remove itself from the list (don't forget to "mutex" it), or you could have another dedicated thread do that: perhaps you could simply have your main thread join all the other threads before exiting.