#include <unistd.h>
#include <stdio.h>
#include <cstring>
#include <thread>
void test_cpu() {
printf("thread: test_cpu start\n");
int total = 0;
while (1) {
++total;
}
}
void test_mem() {
printf("thread: test_mem start\n");
int step = 20;
int size = 10 * 1024 * 1024; // 10Mb
for (int i = 0; i < step; ++i) {
char* tmp = new char[size];
memset(tmp, i, size);
sleep(1);
}
printf("thread: test_mem done\n");
}
int main(int argc, char** argv) {
std::thread t1(test_cpu);
std::thread t2(test_mem);
t1.join();
t2.join();
return 0;
}
Compile it with g++ -o test test.cc --std=c++11 -lpthread
I run the program in Linux, and run top to monitor it.
I expect to see ONE process however I saw THREE.
It looks like std::thread is creating threads, why do I end up with getting processes?
Linux does not implement threads. It only has Light Weight Processes (LWP) while pthread library wraps them to provide POSIX-compatible thread interface. The main LWP creates its own address space while each subsequent thread LWP shares address space with main LWP.
Many utils, such as HTOP (which seems to be on the screenshot) by default list LWP. In order to hide thread LWPs you can open Setup (F2) -> Display Options and check Hide kernel threads and Hide userland process threads options. There is also an option to highlight threads - Display threads in different color.
Related
I have tried to write a program that run in ubuntu terminal .Program will open a new gnome terminal and run command in that new terminal to open new abcd.txt using vim.And then when i Ctrl+C in the first terminal which run the program ,new gnome terminal will shut vim down and have an announcement in the first terminal
I have tried system("`gnome-terminal`<< vim abcd.txt");
and this system("vim abcd.txt>>`gnome-terminal`");
but the new one terminal cannot recieve command
My full code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
int loop=1;
void DEF()
{
system("kill -9 pidof vim");
loop=0;
}
void *subthreads(void *threadid)
{
loop=1;
long tid;
tid=(long)threadid;
system("`gnome-terminal`<< vim abcd.txt");
signal(SIGINT,DEF);
while(loop){}
pthread_exit(NULL);
}
void main()
{
int loop=1;
pthread_t threads;
int check;
long tID;
check= pthread_create(&threads,NULL,&subthreads,(void*)tID);
while(loop){}
printf("Ctrl+C is pressed!\n");
}
Not sure what you are trying to achieve in the end. But here are a few ideas, starting from your code:
The terminal command (in system()) should be something like Mark Setchell pointed out, like for example system("gnome-terminal -e vim file.txt");
The system() command is blocking further execution of your code, so the call to signal() is not happening until you terminate the system() call.
pidof is not working on my Linux system. I would use pkill <program>. Still, that would kill all running instances of , for example vim or your terminal.
You are declaring the variable loop in the global scope first and then redeclaring it in main(). If you really want to use it as a global variable, it should just be loop=1 in main().
You are not using the variable tid for anything.
Here is an improved version of your program, with additional printf calls to explain to the user what is happening. I also used xterm and nano because I don't have gnome-terminal, and I didn't want to interfere with my running instance of vim. But it still is maybe not exactly what you are trying to do. The main problem is that system("xterm -e sh &") is blocking and when you press Ctrl-C, that system call will terminate xterm so that the def() function will do nothing when it is called later.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
int loop = 1;
void def()
{
printf("In def\n");
system("pkill xterm");
loop=0;
}
void *subthreads(void *threadid)
{
printf("Starting subthread\n");
loop = 1;
long tid;
tid = (long)threadid;
signal(SIGINT, def);
system("xterm -e sh -c nano &"); // Note: xterm will still exit when you press Ctrl-C
printf("Terminal exited in subthread\n");
while (loop);
printf("Exited loop in subthread\n");
pthread_exit(NULL);
}
void main()
{
pthread_t threads;
int check;
long tID;
check = pthread_create(&threads, NULL, &subthreads, (void*)tID);
printf("In main after thread creation\n");
while (loop);
printf("Ctrl+C is pressed!\n");
}
Another option is to use fork() instead of pthread to split into a separate process. (Note that processes are like separate applications while threads are processor threads in the same application.)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void def()
{
system("pkill nano");
printf("def(): Killed nano\n");
}
int subprocess()
{
signal(SIGINT, def);
pid_t parent_id = getpid(); // Get process ID of main process
fork(); // Fork into two identical copies of the running app.
if (getpid() != parent_id) { // The part in the if block is only done in the second process!
system("xterm -e sh -c nano &");
printf("subprocess(): system call ended in forked process\n");
exit(0);
}
}
int main()
{
subprocess();
printf("Entering while loop in main process\n");
while (1);
printf("Exited main thread\n");
}
The one flaw with this version is the same as the previous one: when Ctrl-C is pressed, xterm/nano is killed and def() will subsequently do nothing except catch any Ctrl-C done afterwards.
If you explain further what your final goal is, maybe I can give some suggestions.
Like, why do you want to start vim in a terminal from a C application and then kill vim? Do you want to kill the whole terminal or only vim?
std::atomic_signal_fence() Establishes memory synchronization ordering ... between a thread and a signal handler executed on the same thread.
-- cppreference
In order to find an example for this illustration, I looked at bames53's similar question in stackoverflow. However the answer may not suit my x86_64 environment, since x86_64 CPU is strong memory model and forbids Store-Store re-ordering ^1. Its example will correctly execute even without std::atomic_signal_fence() in my x86_64 environment.
So I made a Store-Load re-ordering example suitable for x86_64 after Jeff Preshing's post. The example code is not that short, so I opened this question instead of appending onto bames53's similar question.
main() and signal_handler() will run in the same thread(i.e. they will share the same tid) in a single core environment. main() can be interrupted at any time by signal_handler(). If no signal_fences are used, in the generated binary X = 1; r1 = Y; will be exchanged their ordering if compiled with g++ -O2(Store(X)-Load(Y) is optimized to Load(Y)-Store(X)). The same with Y = 1; r2 = X;. So if main() is interrupted just after 'Load(Y)', it results r1 == 0 and r2 == 0 at last. Thus in the following code line (C) will assert fail. But if line (A) and (B) are uncommented, it should never assert fail since a signal_fence is used to protect synchronization between main() and signal_handler(), to the best of my understanding.
#include <atomic>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <semaphore.h>
#include <signal.h>
#include <unistd.h>
sem_t endSema;
// volatile int synchronizer;
int X, Y;
int r1, r2;
void signal_handler(int sig) {
signal(sig, SIG_IGN);
Y = 1;
// std::atomic_signal_fence(std::memory_order_seq_cst); // (A) if uncommented, assert still may fail
r2 = X;
signal(SIGINT, signal_handler);
sem_post(&endSema); // if changed to the following, assert never fail
// synchronizer = 1;
}
int main(int argc, char* argv[]) {
std::srand(std::time(nullptr));
sem_init(&endSema, 0, 0);
signal(SIGINT, signal_handler);
for (;;) {
while(std::rand() % std::stol(argv[1]) != 0); // argv[1] ~ 1000'000
X = 1;
// std::atomic_signal_fence(std::memory_order_seq_cst); // (B) if uncommented, assert still may fail.
r1 = Y;
sem_wait(&endSema); // if changed to the following, assert never fail
// while (synchronizer == 0); synchronizer = 0;
std::cout << "r1=" << r1 << " r2=" << r2 << std::endl;
if (r1 == 0) assert(r2 != 0); // (C)
Y = 0; r1 = 0; r2 = 0; X = 0;
}
return 0;
}
Firstly semaphore is used to synchronize main() with signal_handler(). In this version, the assert always fail after around received 30 SIGINTs with or without the signal fence. It seems that std::atomic_signal_fence() did not work as I expected.
Secondly If semaphore is replaced with volatile int synchronizer, the program seems never fail with or without the signal fence.
What's wrong with the code? Did I miss-understand the cppreference doc? Or is there any more proper example code for this topic in x86_64 environment that I can observe the effects of std::atomic_signal_fence?
Below is some relevant info:
compiling & running env: CentOS 8 (Linux 4.18.0) x86_64 single CPU core.
Compiler: g++ (GCC) 8.3.1 20190507
Compiling command g++ -std=c++17 -o ordering -O2 ordering.cpp -pthread
Run with ./ordering 1000000, then keep pressing Ctrl-C to invoke the signal handler.
I am unable to find a correct usage of asynchronous thread in c++11.The thing i want to do is i want to spwan threads and each thread will function simultaneously without waiting for each other like thread.join(),which makes other thread to wait until the current thread is done with.So,is there any library in c++ which makes threads to run parallely doing their work simultaneously without having to wait for the other to complete.Actually the thing i want is i want to run each threads sumultaneously, so that they don't wait for the other to complete and its functionality is executed simultaneously without having to wait for others to finish .
Thanks,
Kushal
EDIT:
EDIT:: i am posting the code below
#include <signal.h>
#include <thread>
#include <algorithm>
#include <cstring>
#include <csignal>
#include "paho_client.h"
using namespace std;
vector<string> topic_container{"rpi2/temp","sense /bannana","sense/util","mqtt/temp","sense/temp","sense/pine","sense/fortis/udap"};
vector<paho_client> publisher;
vector<paho_client> subscriber;
int finish_thread=1;
void Onfinish(int signum){
finish_thread=0;
exit(EXIT_FAILURE);
}
int main(int argc, char** argv) {
signal(SIGINT, Onfinish);
int topic_index;
if(argc<3){
cout<<"the format of starting commandline argument is"<<endl;
exit(1);
}
while(finish_thread!=0){
//paho_client::get_library_handle();
if(strcmp(argv[1],"create_publisher")){
for(topic_index=0;topic_index<atoi(argv[2]);topic_index++){
thread pub_th;
pub_th = thread([ = ]() {
paho_client client("publisher", "192.168.0.102", "9876",
topic_container[topic_index].c_str());
client.paho_connect_withpub();
publisher.push_back(client);
});
pub_th.join();
}
vector<paho_client>::iterator it;
int publisher_traverse=0;
for(it=publisher.begin();it<publisher.end();publisher_traverse++){
publisher[publisher_traverse].increment_count();
publisher[publisher_traverse].get_count();
}
}
}
return 0;
}
After using async with future am getting the same behaviour as above please point me where am i going wrong
#include <signal.h>
#include <thread>
#include <algorithm>
#include <cstring>
#include <csignal>
#include <future>
#include "paho_client.h"
using namespace std;
vector<string> topic_container{"rpi2/temp","sense/apple","sense/bannana","sense/util","mqtt/temp","sense/temp","sense/pine","sense/fortis/udap"};
vector<paho_client> publisher;
vector<paho_client> subscriber;
int finish_thread=1;
void Onfinish(int signum){
finish_thread=0;
exit(EXIT_FAILURE);
}
int accumulate_block_worker_ret(int topic_index) {
//int topic_index=0;
paho_client client("publisher", "192.168.0.102", "9876",
topic_container[topic_index].c_str());
client.paho_connect_withpub();
publisher.push_back(client);
client.increment_count();
return client.get_count();
}
int main(int argc, char** argv) {
signal(SIGINT, Onfinish);
if(argc<3){
cout<<"the format of starting commandline argument is . /paho_client_emulate <create_publisher><count of publisher client to spawn>" <<endl;
exit(1);
}
while(finish_thread!=0){
// paho_client::get_library_handle();
int topic_index;
if(strcmp(argv[1],"create_publisher")){
for(topic_index=0;topic_index<atoi(argv[2]);topic_index++){
// thread pub_th;
// pub_th = thread([ = ]() {
future<int> f = async(std::launch::async,accumulate_block_worker_ret,topic_index);
// });
// pub_th.join();
cout<<"the returned value from future is"<<f.get()<<endl;
}
vector<paho_client>::iterator it;
int publisher_traverse=0;
for(it=publisher.begin();it<=publisher.end();publisher_traverse++){
cout<<"came here"<<endl;
publisher[publisher_traverse].increment_count();
publisher[publisher_traverse].get_count();
}
}
}
return 0;
}
i want to launch all the publisher clients first (as threads) and
later publish messages from each threads
The pub_th.join() is misplaced inside the loop where the threads are started, thus waiting for the termination of each thread before starting the next one. To let the threads run in parallel, just move the .join() outside that loop. Of course to access the threads after the loop body, they have to be stored somewhere, e. g. in a vector - for this, change the first for loop to
vector <thread> pub_threads;
for (topic_index=0; topic_index<atoi(argv[2]); topic_index++)
{
pub_threads.push_back(thread([ = ]() { /* whatever */ }));
}
and later when done:
for (auto &th: pub_threads) th.join();
Actually i am running infinite while inside every instance of
paho_client so the first thread is not completed …
that thread is run continously
Of course if never done, there's no point to .join().
I have console C++ application built in XCode 6 and want to add SIGTERM handler to it. There are a lot of examples, but I can't get them to work.
#include <csignal>
namespace
{
volatile std::sig_atomic_t gDone = 0;
}
static void term_handler(int i)
{
gDone = 1;
}
int main(int argc, const char * argv[])
{
std::signal(SIGTERM, term_handler);
while (!gDone);
return 0;
}
The debugger stopped on the while statement, but the handler was not called. The same problem with this code
#include <signal.h>
volatile sig_atomic_t gDone = 0;
void term_handler(int i)
{
gDone = 1;
}
int main(int argc, char* argv[])
{
struct sigaction sa;
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, SIGHUP);
sigprocmask(SIG_BLOCK, &newset, 0);
sa.sa_handler = term_handler;
sigaction(SIGTERM, &sa, 0);
while(!gDone);
return 0;
}
Is there a problem with the code? What is the right way to handle signals in OSX?
After you send the signal, and the debugger stops, you have to continue to get to your breakpoint inside the signal handler.
(lldb) break set -n term_handler
Breakpoint 1: where = a.out`term_handler(int) + 4 at sig.cc:11, address = 0x0000000100000f54
(lldb) run
Process 42532 launched: './a.out' (x86_64)
Process 42532 stopped
* thread #1: tid = 0x18dc39, 0x0000000100000f30 a.out`main(argc=15, argv=0x00007fff5fbffb58) + 32 at sig.cc:17, queue = 'com.apple.main-thread', stop reason = signal SIGTERM
frame #0: 0x0000000100000f30 a.out`main(argc=15, argv=0x00007fff5fbffb58) + 32 at sig.cc:17
14 int main(int argc, const char * argv[])
15 {
16 std::signal(SIGTERM, term_handler);
-> 17 while (!gDone);
18 std::puts("done!");
19 return 0;
20 }
(lldb) c
Process 42532 resuming
Process 42532 stopped
* thread #1: tid = 0x18dc39, 0x0000000100000f54 a.out`term_handler(i=15) + 4 at sig.cc:11, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000f54 a.out`term_handler(i=15) + 4 at sig.cc:11
8
9 static void term_handler(int i)
10 {
-> 11 gDone = 1;
12 }
13
14 int main(int argc, const char * argv[])
(lldb) `
OK, I'm home now and working on my Mac. Again, your code (second sample specifically) has proven just fine. The confirmation was done in Terminal with gcc and "kill -TERM ". Source refers to SIGTERM, like normal, but kill refers (on OS X) to TERM. The XCode pause you are seeing is due to XCode, not your code. I tried it both ways, Terminal and XCode. I could not find a pref to inhibit that interruption, however.
Just to focus here ...You asked, Is there a problem with the code? Answer: No. You asked, What is the right way to handle signals in OSX? Answer: The way you're already doing it. New question: How do I get XCode (lldb) to not pause when signals occur? Answer: How to tell LLDB debugger not to handle SIGBUS?
Your code is fine. Kill with:
kill -SIGTERM 31573
because
kill -9 31573
where 31573 was my process ID, did not exit gracefully. I added a printf to your code to tell me it was exiting gracefully.
I have the following code that is supposed to process ever wile with a .NEF extension.
#include <iostream>
#include <regex>
#include <pthread.h>
#include <dirent.h>
using namespace std;
void *workHorse(void*);
int main (int argc, char *argv[]){
pthread_t t1;
int rc, pos1;
DIR *dir;
struct dirent *ent;
regex e("(.*)(\\.)(NEF|nef)");
if ((dir = opendir (".")) != NULL) {
string fn1;
while ((ent = readdir (dir))!=NULL){
fn1.assign(ent->d_name);
if (regex_match ( fn1, e )){
cout<<"F :"<<fn1.c_str()<<" "<<endl;
if (rc=pthread_create( &t1, NULL, &workHorse, (void*)&fn1)){
cout<<"Error creating threads "<<rc<<endl;
exit(-1);
}
}
}
}
return 0;
}
void *workHorse(void *fileName){
int ret;
cout<<"W :"<<((string*)fileName)->c_str()<<endl;
pthread_exit(NULL);
}
There is just one file with .NEF extension in the directory. My expected output is -
F :DSC_0838.NEF
W :DSC_0838.NEF
However, I get
F :DSC_0838.NEF
W :RGBbmp.bmp
RGBbmp.bmp is another file in the same directory. What is wrong with my code? Why does it not work as expected?
The above code was compiled using -
g++ tmp.cpp -pthread --std=c++11
fn1's address is shared between the main thread and the secondary p_thread you create.
While the new thread is bootstrapping, the main thread changes the value in 'fn1' memory address, and the secondary thread reads the name of a different file (because in the main thread fn1 now has a new value).
You need to create a copy of the string you pass to the secondary thread, or you need to syncrhonize your read/write, I would recommend the former since it is way easier.
In this line:
if (rc=pthread_create( &t1, NULL, &workHorse, (void*)&fn1))
You are passing the address of fn1, the value then is changed in the main loop to some other file names, and by the time the tread comes up, it is now in RGBbmp.bmp