C++ killing child thread stops execution of the main thread - c++

I am completely confused with timers and how threads (pthread) work in C++
Timers arent timers but clocks and you cant (I at least cant) kill a thread without killing main thread.
What I need - a bit of code which executes once in 24hrs on a separate thread.
However if the app needs to stop it - I cant do anything but send SIGKILL to it (because join will wait till midnight). Once I kill that thread the app (main thread) seems to kill itself also.
I am open to suggestions.
On condition - I cannot use std::threads and I dont want to wake this thread more than once a day
But easiest for me would be to kill a child thread without stopping execution of the main thread (why this is the case anyway??)
Here is the sample:
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <thread>
#include <pthread.h>
#include <signal.h>
using namespace std;
void* Logger(void* arg) {
int* thread_state = (int*)arg;
cout << "Logger started" << endl;
sleep(24 * 60 * 60);
cout << "Logger thread exiting" << endl;
pthread_exit(0);
}
int main()
{
int thread_state = 0;
pthread_t logger_t;
int rc = pthread_create(&logger_t, NULL, Logger, (void*)&thread_state);
sleep(2);
//thread_state = 1;
pthread_kill(logger_t, SIGKILL);
cout << "i wuz here" << endl;
return 0;
}
output:
Logger started
Killed

I dont know how I missed it but if I call pthread_cancel instead of pthread_kill it works just fine.

Related

Call a function after x seconds while keep running rest of the program in C++

I have a program in which I want to call a function after x seconds or minutes while keep running rest of the program.
You should run new thread:
#include <string>
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
// The function we want to execute on the new thread.
void task(int sleep)
{
std::this_thread::sleep_for (std::chrono::seconds(sleep));
cout << "print after " << sleep << " seconds" << endl;
}
int main()
{
// Constructs the new thread and runs it. Does not block execution.
thread t1(task, 5);
// Do other things...
// Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
t1.join();
}

Missing notification of condition variable

In the following code I've a worker thread which is going to have one major state - Started. Started isn't the thread launch state but the state when a blocking call finally returns which I've replaced with a random delay and comment.
What I'm trying here is to first launch the worker thread asap, block on it's blocking call while keeping started = false till it doesn't returns. As soon as it returns, I'll put started = true and notify main thread's infinite loop to launch another thread and wait again. The previous worker thread can resume doing its work now. And then repeat this process. The launch of new thread must wait for the START state of previous thread.
But in my previous question, someone mentioned this -
If cv.notify_one is called before cv.wait is running the notification
will be missed. In the presented code it most probably will.
For now I tried to manually test it in various ways possible but couldn't get an error and everything is working as I thought. So I want to know in what situation will it actually miss it, anyway to make it reproducible, and how to actually solve it if it is a problem?
#include <iostream>
#include <string>
#include <mutex>
#include <condition_variable>
#include <future>
#include <atomic>
#include <chrono>
#include <thread>
#include <random>
std::mt19937_64 eng{std::random_device{}()};
std::uniform_int_distribution<> dist{100, 2000};
std::mutex m;
std::condition_variable cv;
bool started = false;
std::atomic<int> count(0);
void worker_thread()
{
std::unique_lock<std::mutex> lk(m);
int local_cnt = count++;
// some blocking call represented by random delay
std::this_thread::sleep_for(std::chrono::milliseconds{dist(eng)});
std::cerr << "Enter Accept: " << local_cnt << "\n";
started = true;
lk.unlock();
cv.notify_one(); // notify to launch other threads
// complete other work here
std::this_thread::sleep_for(std::chrono::milliseconds{dist(eng) + 2000});
std::cerr << "Exit Accept: " << local_cnt << "\n";
}
int main()
{
while(1){
std::thread(worker_thread).detach();
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return started;});
started = false;
}
}

SIGTSTP signal not stopping child?

I'm trying to write a program that forks, the child executes a command and then returns control to the parent. I am having trouble getting the SIGTSTP (C-z) signal to work as intended, though... I want the parent to ignore it, but the child to stop and return control to the parent, so that the child can later be resumed or killed (with a builtin command). I isolated the relevant code into a smaller program just to test it, and it seems like A) the child doesn't stop when C-z is typed, or B) it does stop, but does not return control to the parent (I'm leaning towards this because when I use cat for stdin, it behaves differently after the C-z). Here is my code.
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <cstring>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <string>
#include <signal.h>
int main(){
std::cout.setf(std::ios::unitbuf);
std::vector<std::string> vec; vec.push_back("cat");
std::vector<char*> chvec;
for(unsigned int i = 0; i < vec.size(); i++){
chvec.push_back(&vec[i][0]);
}
chvec.push_back(NULL);
vec.erase(vec.begin(), vec.begin() + chvec.size());
char** argv = &chvec[0];
signal(SIGTSTP,SIG_IGN);
pid_t pid;
if((pid = fork()) == 0){
signal(SIGTSTP,SIG_DFL);
/*pid = getpid();
setpgid(pid,pid);*/
std::cout << "before exec" << std::endl;
execvp(argv[0],argv);
perror("exec");
}
else{
//setpgid(pid,pid);
int status;
waitpid(pid,&status,0);
if(WIFEXITED(status) || WIFSIGNALED(status)){
std::cout << "exited or signaled" << std::endl;
}
if(WIFSTOPPED(status)){
std::cout << "process stopped" << std::endl;
}
//std::cout << "process exited" << std::endl;
pause();
}
return EXIT_SUCCESS;
}
It was already pointed out in the comments that you need to fix the undefined behavior as a result of the vec vector being erased. That's the first problem.
I see that your code is checking the exit status of a process using WIFSTOPPED.
Let's review the documentation for the wait(2) system call, and see what it says about this:
WIFSTOPPED(wstatus)
returns true if the child process was stopped by delivery of a
signal; this is possible only if the call was done using WUN‐
TRACED or when the child is being traced (see ptrace(2)).
So, with that information at hand, after fixing the previously mentioned undefined behavior, and after changing your waitpid() call to:
waitpid(pid,&status,WUNTRACED);
Then I was able to send a kill -TSTP <pid> message to the spawned cat process, and obtain the expected
process stopped
message from your test program.
P.S. By stracing the child process, I could see that the child process was receiving the TSTP signal, and stopping just fine. The issue was simply that the parent wasn't handling it, without the required option to waitpid().

Threads exiting prematurely

I have the following piece of code, meant to create two threads and execute them indefinitely. But when run, it exits after some iterations.
#include <iostream>
#include "error.h"
#include <cstdlib>
#include <pthread.h>
#include <string>
#include <time.h>
#include <sys/wait.h>
using namespace std;
#define NUM_THREADS 2
#define TIME_OUT 3
void *GoBackN(void* arg) {
while(true) cout<<"Thread executing"<<endl;
}
int main()
{
pthread_t t[NUM_THREADS];
pthread_create((&t[0]),NULL,&GoBackN,NULL);
pthread_create((&t[1]),NULL,&GoBackN,NULL);
wait(NULL);
return 0;
}
Output -
Thread executing
Thread executing
Thread executing
Thread executing
Thread executing
Thread executing
Thread executing
Thread executing
Thread executing
Thread executing
Thread executing
Process returned 0;
I'm compiling on g++, and running a linux machine.
You have three threads and you allow the main thread to exit.
#include <iostream>
#include "error.h"
#include <cstdlib>
#include <pthread.h>
#include <string>
#include <time.h>
#include <sys/wait.h>
using namespace std;
#define NUM_THREADS 2
#define TIME_OUT 3
void* GoBackN(void* arg) {
while(true) cout<<"Thread executing"<<endl;
}
int main() // main thread starts here
{
pthread_t t[NUM_THREADS];
pthread_create((&t[0]),NULL,&GoBackN,NULL); // second thread starts here
pthread_create((&t[1]),NULL,&GoBackN,NULL); // third thread starts here
wait(NULL); // doesn't wait for very long (zero time)
// ...
// main thread keeps running here...
// ...
return 0; // whoops main thread ends closing program
}
You could put an infinite loop (or an infinite wait) in the main thread to stop it exiting the program.
int main()
{
pthread_t t[NUM_THREADS];
pthread_create((&t[0]),NULL,&GoBackN,NULL);
pthread_create((&t[1]),NULL,&GoBackN,NULL);
wait(NULL); // doesn't wait for very long (zero time)
// ...
// loop in the main thread too
while(true) cout<<"Main thread executing"<<endl;
// ...
return 0; // now we don't get here
}
Or more typically join the threads waiting for them to exit:
int main() // main thread starts here
{
pthread_t t[NUM_THREADS];
pthread_create((&t[0]),NULL,&GoBackN,NULL); // second thread starts here
pthread_create((&t[1]),NULL,&GoBackN,NULL); // third thread starts here
wait(NULL); // doesn't wait for very long (zero time)
// ...
// join threads here
pthread_join(t[0], nullptr);
pthread_join(t[1], nullptr);
// ...
return 0; // we get here when other threads end
}
Now the main thread is suspended and does not consume any CPU time while the other threads are running.
If you are using a modern compiler with C++11 support you can use the Standard Library threads something like this:
#include <thread>
#include <chrono>
#include <vector>
#include <sstream>
#include <iostream>
const int number_of_threads = 5;
// nasty little MACRO to provide synchronized output (crude but works)
#define SYNC_OUT(m) do{std::ostringstream o; o << m << '\n'; std::cout << o.str();}while(0)
void GoBackN(int id) {
while(true)
{
SYNC_OUT("Thread: " << id << " executing");
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
int main() // main thread starts here
{
std::vector<std::thread> threads;
for(int i = 0; i < number_of_threads; ++i)
threads.emplace_back(GoBackN, i); // start new thread
// ...
// join threads here
for(auto&& thread: threads)
thread.join();
}
I'd recommend using <thread> or <future>s std::async. After you create threads, you should either .join() them later or .detach() them, whereas .join() halts the main programs execution and .detach() does not.
#include <thread>
#include <iostream>
void foo()
{
std::cout << "print from thread" << std::endl;
}
int main()
{
std::cout << "before the thread starts" << std::endl;
std::thread t(foo);
t.join();
std::cout << "after thread finishes" << std::endl;
}
For more information you really should check out this for example.

Do objects gets destroyed properly with kill?

In the following, the child process creates the object. It uses signal to kill itself after certain period of time:
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
class Wut{
public:
Wut(){cout<<"obj being created" << endl;}
~Wut(){cout<<"obj being destroyeed" << endl;}
};
void alarmHandler(){
cout << "Alarm! Forcing child to kill itself" << endl;
kill(getpid(), SIGKILL);
}
int main(int argc, char* argv[]){
int status;
pid_t pid;
if((pid = fork()) == 0){
Wut hi;
signal(SIGALRM, (sighandler_t)alarmHandler);
alarm(1);
alarm(7);
sleep(10);
cout << "this will not get printed" << endl;
} else {
wait(&status);
cout << "Parent dies" << endl;
}
sleep(10);
return 0;
}
But I am not sure if the object it creates gets destroyed properly because it never calls the destructor.
The KILL signal is actually not sent to the process; it's a signal for the operating system to forcibly stop the program execution. That means that destructors will not be called.
Use a signal like SIGTERM to see the expected behaviour:
kill(getpid(), SIGTERM);
Unix processes can't handle SIGKILL in any way. Your process is dead as a doornail, immediately. If you want a graceful exit, look into SIGTERM. You can then register a handler to do whatever cleanup you need.
You can use the handler to put your program into a state where it exits normally (e.g. by setting a flag or such), allowing the destructors to run.
SIGKILL is (in most cases) the same as kill -9, so all of the memory allocated to that process is reclaimed by the operating system.