linux c++ use std::thread join, throw exception - c++

my project use three Level process mode. In order to the code after the fork does not inherit from the worker thread of the previous process, so create sub thread to fork sub process when each called.
Now, I found some problems at following describe:
1. the grandson process create a std::thread(work_thread), when called the join() method, it's throw a exception
2. if the son process dose not in sub thread call fork() method, then it's does not thow exception
3. if in grandson process create a empty std::thread(it's nothing to do) before the work thread create, and the empty thread called join() method after the work thread called join() , then it is does not throw the exception. but if the empty thread called join() before work thread, it's also throw the same exception
if you can help me, please write your answer, i will thank you very much
the following code is test case:
#include <iostream>
#include <unistd.h>
#include <wait.h>
#include <thread>
using namespace std;
int main(int argc, char **argv)
{
std::thread t([]() {
int l2pid = fork();
if(l2pid > 0)
waitpid(l2pid, NULL, 0);
else if (l2pid == 0)
{
std::thread t2([]() {
int l3pid = fork();
if (l3pid > 0)
waitpid(l3pid, NULL, 0);
else if (l3pid == 0){
//std::thread empty_thread([](){
//});
std::thread work_thread([](){
for(int i = 0; i < 5; i++){
std::cout << "working..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
});
if(work_thread.joinable())
work_thread.join();
//if(empty_thread.joinable())
// empty_thread.join();
std::cout << "L3 Process Exit!" << std::endl;
}
});
if (t2.joinable())
t2.join();
std::cout << "L2 Process Exit!" << std::endl;
}
});
if (t.joinable())
t.join();
std::cout << "Main Process Exit!" << std::endl;
return 0;
}
i use pthread_create and pthread_join also return EDEADLK
#include <iostream>
#include <unistd.h>
#include <wait.h>
#include <thread>
#include <vector>
#include <pthread.h>
using namespace std;
void *work_thread(void *)
{
for (int i = 0; i < 5; i++)
{
std::cout << "working..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return NULL;
}
void *t2_function(void *)
{
int l3pid = fork();
if (l3pid > 0)
{
waitpid(l3pid, NULL, 0);
}
else if (l3pid == 0)
{
pthread_t thread_handle;
int ret = pthread_create(&thread_handle, NULL, work_thread, NULL);
std::this_thread::sleep_for(std::chrono::seconds(3));
void *pthread_ret = NULL;
std::cout << "thread_handle:" << thread_handle << ",pthread_self:" << pthread_self() << std::endl;
ret = pthread_join(thread_handle, &pthread_ret);
std::cout << "pthread_join:" << ret << std::endl;
std::cout << "L3 Process Exit!" << std::endl;
}
}
void * t1_function(void *)
{
int l2pid = fork();
if (l2pid > 0)
waitpid(l2pid, NULL, 0);
else if (l2pid == 0)
{
pthread_t l2;
pthread_create(&l2, NULL, t2_function, NULL);
pthread_join(l2, NULL);
std::cout << "L2 Process Exit!" << std::endl;
}
}
int main(int argc, char **argv)
{
pthread_t l1;
pthread_create(&l1, NULL, t1_function, NULL);
pthread_join(l1, NULL);
std::cout << "L1 Process Exit!" << std::endl;
return 0;
}

Related

Use pthread_cancel in QNX system has a memory leak, but it does not exist on the Linux system

I have a code, main thread create 2 thread(thread_1 and thread_2), I use pthread_cancel to cancel thread_1 in thread_2, but the data that I create in thread_1 will not be destructored when I run it in QNX system, but there is no problem in Linux system.
It my test code, when I run it in QNX system,MyClass and MyClass2 object destructor not be called, so the 100M memory will leak; but run it in Linux system,it will call MyClass and MyClass2 object destructor. why is there such a difference???
#include <iostream>
#include <pthread.h>
#include <thread>
using namespace std;
pthread_t thread_id_1;
pthread_t thread_id_2;
class MyClass2
{
public:
MyClass2() {
cout << "Build MyClass2" << endl;
}
~MyClass2() {
cout << "Destory MyClass2" << endl;
}
};
class MyClass
{
public:
MyClass() {
cout << "Build MyClass" << endl;
p = (char *)malloc(1024 * 1024 *100);
}
~MyClass() {
cout << "Destory MyClass" << endl;
free(p);
}
char *p;
};
void func(int i)
{
MyClass2 c2;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
cout << "thread 1 func:" << i << endl;
}
static void *thread_1(void *arg)
{
MyClass my_class;
int type_value = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
cout << "thread_1 set cancle type+++++:" << type_value << endl;
for (int i = 0; i < 10; i++) {
func(i);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
return nullptr;
}
static void *thread_2(void *arg)
{
for (int i = 0; i < 10; i++) {
cout << "thread_2:" << i << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
int ret = pthread_cancel(thread_id_1);
cout << "otx_thread_2 cancel thread 1 ret:" << ret << endl;
return nullptr;
}
int main(int argc, char *argv[])
{
cout << "Main start" << endl;
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
cout << "Main set detch" << endl;
if (pthread_create(&thread_id_1, &attr, thread_1, nullptr) != 0) {
cout << "pthread_create() 1 error" << endl;
return -1;
}
if (pthread_create(&thread_id_2, nullptr, thread_2, nullptr) != 0) {
cout << "pthread_create() 2 error" << endl;
return -1;
}
if (pthread_join(thread_id_2, NULL) != 0) {
cout << "pthread_join() 1 error";
return -1;
}
while (1) {
cout << "Main Loop" << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
return 0;
}
enter image description here
enter image description here
I try it again and again, so I confirm that there is no problem with the code, But I don't understand why there is such a difference
pthread_cancel is outside the scope of the C++ specification. C++ does not specify its behavior, nor inherit it from C or POSIX.
The difference is simply because QNX and Linux have implemented pthread_cancel differently in a C++ environment. There is literally nothing more to it than that.
I imagine that the QNX implementation stops the thread in its tracks, whereas the Linux implementation probably induces an exception which unwinds the canceled thread's stack.

C++ Condition variable to signal end of detached thread execution stalls

I have some code which I'm working on where a detached thread is spawned, does some work, and then should wait for a signal from main() before sending another signal back to main indicating that the thread has quit.
I'm fairly new to condition variables, however I have worked with some multi thread code before. (Mostly mutexes.)
This is what I tried to implement, but it doesn't behave the way I would have expected. (Likely I misunderstood something.)
The idea behind this is to pass a struct containing two flags to each detached thread. The first flag indicates that main() says "it is ok to exit, and drop off the end of the thread function". The second flag is set by the thread itself and signals to main() that the thread has indeed exited. (It's just to confirm the signal from main() is recieved ok and to send something back.)
#include <cstdlib> // std::atoi
#include <iostream>
#include <thread>
#include <vector>
#include <random>
#include <future>
#include <condition_variable>
#include <mutex>
struct ThreadStruct
{
int id;
std::condition_variable cv;
std::mutex m;
int ok_to_exit;
int exit_confirm;
};
void Pause()
{
std::cout << "Press enter to continue" << std::endl;
std::cin.get();
}
void detachedThread(ThreadStruct* threadData)
{
std::cout << "START: Detached Thread " << threadData->id << std::endl;
// Performs some arbitrary amount of work.
for(int i = 0; i < 100000; ++ i);
std::cout << "FINISH: Detached thread " << threadData->id << std::endl;
std::unique_lock<std::mutex> lock(threadData->m);
std::cout << "WAIT: Detached thread " << threadData->id << std::endl;
threadData->cv.wait(lock, [threadData]{return threadData->ok_to_exit == 1;});
std::cout << "EXIT: Detached thread " << threadData->id << std::endl;
threadData->exit_confirm = 1;
}
int main(int argc, char** argv)
{
int totalThreadCount = 1;
ThreadStruct* perThreadData = new ThreadStruct[totalThreadCount];
std::cout << "Main thread starting " << totalThreadCount << " thread(s)" << std::endl;
for(int i = totalThreadCount - 1; i >= 0; --i)
{
perThreadData[i].id = i;
perThreadData[i].ok_to_exit = 0;
perThreadData[i].exit_confirm = 0;
std::thread t(detachedThread, &perThreadData[i]);
t.detach();
}
for(int i{0}; i < totalThreadCount; ++i)
{
ThreadStruct *threadData = &perThreadData[i];
std::cout << "Waiting for lock - main() thread" << std::endl;
std::unique_lock<std::mutex> lock(perThreadData[i].m);
std::cout << "Lock obtained - main() thread" << std::endl;
perThreadData[i].cv.wait(lock);
threadData->ok_to_exit = 1;
// added after comment from Sergey
threadData->cv.notify_all();
std::cout << "Done - main() thread" << std::endl;
}
for(int i{0}; i < totalThreadCount; ++i)
{
std::size_t thread_index = i;
ThreadStruct& threadData = perThreadData[thread_index];
std::unique_lock<std::mutex> lock(threadData.m);
std::cout << "i=" << i << std::endl;
int &exit_confirm = threadData.exit_confirm;
threadData.cv.wait(lock, [exit_confirm]{return exit_confirm == 1;});
std::cout << "i=" << i << " finished!" << std::endl;
}
Pause();
return 0;
}
This runs to the line:
WAIT: Detached thread 0
but the detached thread never quits. What have I done wrong?
Edit: Further experimentation - is this helpful?
I thought it might be helpful to simplify things by removing a step. In the example below, main() does not signal to the detached thread, it just waits for a signal from the detached thread.
But again, this code hangs - after printing DROP... This means the detached thread exits ok, but main() doesn't know about it.
#include <cstdlib> // std::atoi
#include <iostream>
#include <thread>
#include <vector>
#include <random>
#include <future>
#include <condition_variable>
#include <mutex>
struct ThreadStruct
{
int id;
std::condition_variable cv;
std::mutex m;
int ok_to_exit;
int exit_confirm;
};
void Pause()
{
std::cout << "Press enter to continue" << std::endl;
std::cin.get();
}
void detachedThread(ThreadStruct* threadData)
{
std::cout << "START: Detached Thread " << threadData->id << std::endl;
// Performs some arbitrary amount of work.
for(int i = 0; i < 100000; ++ i);
std::cout << "FINISH: Detached thread " << threadData->id << std::endl;
std::unique_lock<std::mutex> lock(threadData->m);
std::cout << "EXIT: Detached thread " << threadData->id << std::endl;
threadData->exit_confirm = 1;
threadData->cv.notify_all();
std::cout << "DROP" << std::endl;
}
int main(int argc, char** argv)
{
int totalThreadCount = 1;
ThreadStruct* perThreadData = new ThreadStruct[totalThreadCount];
std::cout << "Main thread starting " << totalThreadCount << " thread(s)" << std::endl;
for(int i = totalThreadCount - 1; i >= 0; --i)
{
perThreadData[i].id = i;
perThreadData[i].ok_to_exit = 0;
perThreadData[i].exit_confirm = 0;
std::thread t(detachedThread, &perThreadData[i]);
t.detach();
}
for(int i{0}; i < totalThreadCount; ++i)
{
std::size_t thread_index = i;
ThreadStruct& threadData = perThreadData[thread_index];
std::cout << "Waiting for mutex" << std::endl;
std::unique_lock<std::mutex> lock(threadData.m);
std::cout << "i=" << i << std::endl;
int &exit_confirm = threadData.exit_confirm;
threadData.cv.wait(lock, [exit_confirm]{return exit_confirm == 1;});
std::cout << "i=" << i << " finished!" << std::endl;
}
Pause();
return 0;
}
Your lambda is capturing by-value so it will never see the changes made to exit_confim.
Capture by-reference instead:
int& exit_confirm = threadData.exit_confirm;
threadData.cv.wait(lock, [&exit_confirm] { return exit_confirm == 1; });
// ^
// | capture by-reference
You also need to delete[] what you new[] so do
delete[] ThreadStruct;
when you're done with the the structs.
I also noticed some heap usage after free but that magically went away when I made some simplifications to the code. I didn't investigate that further.
Some suggestions:
Move code into the ThreadStruct class that deals with ThreadStruct member variables and locks. It usually makes it simpler to read and maintain.
Remove unused variables and headers.
Don't use new[]/delete[]. For this example, you could use a std::vector<ThreadStruct> instead.
Don't detach() at all - I haven't done anything about that below, but I suggest using join() (on attached threads) to do the final synchronization. That's what it's there for.
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
struct ThreadStruct {
int id;
// move this function into the ThreadStruct class
void detachedThread() {
std::cout << "START: Detached Thread " << id << std::endl;
// Performs some arbitrary amount of work (optimized away here)
std::cout << "FINISH: Detached thread " << id << std::endl;
std::lock_guard<std::mutex> lock(m);
std::cout << "EXIT: Detached thread " << id << std::endl;
exit_confirm = 1;
cv.notify_all();
std::cout << "DROP" << std::endl;
}
// add support functions instead of doing these things in your normal code
void wait_for_exit_confirm() {
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [this] { return exit_confirm == 1; });
}
void spawn_detached() {
std::thread(&ThreadStruct::detachedThread, this).detach();
}
private:
std::condition_variable cv;
std::mutex m;
int exit_confirm = 0; // initialize
};
With the above, main becomes a little cleaner:
int main() {
int totalThreadCount = 1;
std::vector<ThreadStruct> perThreadData(totalThreadCount);
std::cout << "Main thread starting " << perThreadData.size() << " thread(s)\n";
int i = 0;
for(auto& threadData : perThreadData) {
threadData.id = i++;
threadData.spawn_detached();
}
for(auto& threadData : perThreadData) {
std::cout << "Waiting for mutex" << std::endl;
std::cout << "i=" << threadData.id << std::endl;
threadData.wait_for_exit_confirm();
std::cout << "i=" << threadData.id << " finished!" << std::endl;
}
std::cout << "Press enter to continue" << std::endl;
std::cin.get();
}
For future interest: fixed the origional MWE posted in the question. There was two issues
not capturing local variable in lambda by reference (see other answer)
1 too many wait() calls
#include <cstdlib> // std::atoi
#include <iostream>
#include <thread>
#include <vector>
#include <random>
#include <future>
#include <condition_variable>
#include <mutex>
struct ThreadStruct
{
int id;
std::condition_variable cv;
std::mutex m;
int ok_to_exit;
int exit_confirm;
};
void Pause()
{
std::cout << "Press enter to continue" << std::endl;
std::cin.get();
}
void detachedThread(ThreadStruct* threadData)
{
std::cout << "START: Detached Thread " << threadData->id << std::endl;
// Performs some arbitrary amount of work.
for (int i = 0; i < 100000; ++i);
std::cout << "FINISH: Detached thread " << threadData->id << std::endl;
std::unique_lock<std::mutex> lock(threadData->m);
std::cout << "WAIT: Detached thread " << threadData->id << std::endl;
threadData->cv.wait(lock, [&threadData]{return threadData->ok_to_exit == 1;});
std::cout << "EXIT: Detached thread " << threadData->id << std::endl;
threadData->exit_confirm = 1;
threadData->cv.notify_all();
std::cout << "DROP" << std::endl;
}
int main(int argc, char** argv)
{
int totalThreadCount = 1;
ThreadStruct* perThreadData = new ThreadStruct[totalThreadCount];
std::cout << "Main thread starting " << totalThreadCount << " thread(s)" << std::endl;
for (int i = totalThreadCount - 1; i >= 0; --i)
{
perThreadData[i].id = i;
perThreadData[i].ok_to_exit = 0;
perThreadData[i].exit_confirm = 0;
std::thread t(detachedThread, &perThreadData[i]);
t.detach();
}
for(int i{0}; i < totalThreadCount; ++ i)
{
ThreadStruct *threadData = &perThreadData[i];
std::cout << "Waiting for lock - main() thread" << std::endl;
std::unique_lock<std::mutex> lock(perThreadData[i].m);
std::cout << "Lock obtained - main() thread" << std::endl;
//perThreadData[i].cv.wait(lock, [&threadData]{return threadData->ok_to_exit == 1;});
std::cout << "Wait complete" << std::endl;
threadData->ok_to_exit = 1;
threadData->cv.notify_all();
std::cout << "Done - main() thread" << std::endl;
}
for (int i{ 0 }; i < totalThreadCount; ++i)
{
std::size_t thread_index = i;
ThreadStruct& threadData = perThreadData[thread_index];
std::cout << "Waiting for mutex" << std::endl;
std::unique_lock<std::mutex> lock(threadData.m);
std::cout << "i=" << i << std::endl;
int& exit_confirm = threadData.exit_confirm;
threadData.cv.wait(lock, [&exit_confirm] {return exit_confirm == 1; });
std::cout << "i=" << i << " finished!" << std::endl;
}
Pause();
return 0;
}

How to initialized pthread_t variable in class constructor

How to initialized pthread_t variable in class constructor.
C++ Static Analysis(coverity) Error: Non-static class member threadId is not initialized in this constructor nor in any functions that it calls.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void *
threadFunc(void * arg)
{
std::cout << "Thread Function :: Start" << std::endl;
// Sleep for 2 seconds
sleep(2);
std::cout << "Thread Function :: End" << std::endl;
return NULL;
}
class threads
{
private:
pthread_t threadId;
int err;
public:
threads():err(0){};
~threads(){};
void create_thread();
void join_thread();
};
void
threads::create_thread()
{
// Create a thread that will function threadFunc()
err = pthread_create(&threadId, NULL, &threadFunc, NULL);
// Check if thread is created sucessfuly
if (err)
{
std::cout << "Thread creation failed : " << strerror(err);
}
else
{
std::cout << "Thread Created with ID : " << threadId << std::endl;
}
}
void
threads::join_thread()
{
err = pthread_join(threadId, NULL);
// check if joining is sucessful
if (err)
{
std::cout << "Failed to join Thread : " << strerror(err) << std::endl;
}
}
int main()
{
threads T;
T.create_thread();
T.join_thread();
std::cout << "Exiting Main" << std::endl;
return 0;
}
Note:
I have checked all existing questions and answer in Stackoverflow.
But none of them have clear answer.
The above c++ code is a sample code(copied from Internet and updated to show my actual problem)
I have tried this and its working (Posting the answer, to help others)
#include <iostream>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void *
threadFunc(void * arg)
{
std::cout << "Thread Function :: Start" << std::endl;
// Sleep for 2 seconds
sleep(2);
std::cout << "Thread Function :: End" << std::endl;
return NULL;
}
class threads
{
private:
pthread_t threadId;
int err;
public:
threads():err(0){ threadId = pthread_t(); std::cout <<threadId<<std::endl;};
~threads(){};
void create_thread();
void join_thread();
};
void
threads::create_thread()
{
// Create a thread that will function threadFunc()
err = pthread_create(&threadId, NULL, &threadFunc, NULL);
// Check if thread is created sucessfuly
if (err)
{
std::cout << "Thread creation failed : " << strerror(err);
}
else
{
std::cout << "Thread Created with ID : " << threadId << std::endl;
}
}
void
threads::join_thread()
{
err = pthread_join(threadId, NULL);
// check if joining is sucessful
if (err)
{
std::cout << "Failed to join Thread : " << strerror(err) << std::endl;
}
}
int main()
{
threads T;
T.create_thread();
T.join_thread();
std::cout << "Exiting Main" << std::endl;
return 0;
}

Is it possible to build a concurrent interprocess message queue using boost?

I am trying to build an application which have multiple processes. These processes need to write concurrently through the same message queue. At the other side, there will be just one process reading that queue.
Is that possible using boost? Or do I have to implement that mutual exclusion?
I took a look at the example source code but it is not working properly for my needs. I don't know if I'm missing something.
This is the code on the client:
#include <boost/interprocess/ipc/message_queue.hpp>
#include <iostream>
#include <vector>
#include <unistd.h>
using namespace boost::interprocess;
int main ()
{
try{
//Erase previous message queue
//message_queue::remove("message_queue");
//Create a message_queue.
message_queue mq
(open_or_create //only create
,"message_queue" //name
,100 //max message number
,sizeof(int) //max message size
);
//Send 100 numbers
for(int i = 0; i < 100; ++i){
printf("Sending: %d\n", i);
usleep(1000000);
mq.send(&i, sizeof(i), 0);
}
}
catch(interprocess_exception &ex){
std::cout << ex.what() << std::endl;
return 1;
}
return 0;
}
And server code:
#include <boost/interprocess/ipc/message_queue.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace boost::interprocess;
int main ()
{
try{
//message_queue::remove("message_queue");
//Open a message queue.
message_queue mq
(open_only //only create
,"message_queue" //name
);
unsigned int priority;
message_queue::size_type recvd_size;
//Receive 100 numbers
for(int i = 0; i < 100; ++i){
int number;
mq.receive(&number, sizeof(number), recvd_size, priority);
if(number != i || recvd_size != sizeof(number))
return 1;
cout << number << endl;
}
}
catch(interprocess_exception &ex){
message_queue::remove("message_queue");
std::cout << ex.what() << std::endl;
return 1;
}
//message_queue::remove("message_queue");
return 0;
}
Thanks in advance.
The given examples for boost::interprocess::message_queue work for me. These classes are already thread-safe, so intra-process threads are not a problem.
Here's a full example of a shared message queue. Let me know if you have trouble using it.
shared_mq.hpp:
#include <boost/interprocess/ipc/message_queue.hpp>
// could easily be made a template; make sure T is a POD!
class shared_mq {
public:
shared_mq(const char* const name,
const unsigned max_queue_size) :
shared_mq{ name, max_queue_size, delete_queue(name) }
{}
shared_mq(const char* const name) :
mq_{ boost::interprocess::open_only, name }
{}
void send(int i) {
mq_.send(&i, sizeof(i), 0 /* priority */);
}
int receive() {
int result;
boost::interprocess::message_queue::size_type recvsize;
unsigned recvpriority;
mq_.receive(&result, sizeof(result), recvsize, recvpriority);
return result;
}
private:
struct did_delete_t {};
did_delete_t delete_queue(const char* const name) {
boost::interprocess::message_queue::remove(name);
return did_delete_t{};
}
shared_mq(const char* const name,
const unsigned max_queue_size,
did_delete_t) :
mq_ { boost::interprocess::create_only, name, max_queue_size, sizeof(int) }
{}
boost::interprocess::message_queue mq_;
};
client.cpp:
#include <iostream>
#include <random>
#include <thread>
#include "shared_mq.hpp"
void send_ints(shared_mq& mq, const unsigned count) {
std::random_device rd;
std::mt19937 mt{ rd() };
std::uniform_int_distribution<int> dist{0, 10000};
for (unsigned i = 0; i != count; ++i) {
mq.send(dist(mt));
}
}
int main ()
{
std::cout << "Starting client." << std::endl;
try {
std::cout << "Creating queue..." << std::endl;
constexpr unsigned kQueueSize = 100;
shared_mq mq{ "my_queue", kQueueSize };
std::cout << "Sending ints..." << std::endl;
std::thread t1{ send_ints, std::ref(mq), 25};
std::thread t2{ send_ints, std::ref(mq), 25};
t1.join();
t2.join();
mq.send(-1); // magic sentinel value
}
catch (boost::interprocess::interprocess_exception& ex) {
std::cerr << ex.what() << std::endl;
return 1;
}
std::cout << "Finished client." << std::endl;
return 0;
}
server.cpp:
#include <iostream>
#include "shared_mq.hpp"
int main ()
{
std::cout << "Starting server." << std::endl;
try {
std::cout << "Opening queue..." << std::endl;
shared_mq mq{ "my_queue" };
std::cout << "Receiving ints..." << std::endl;
for (;;) {
const int x = mq.receive();
if (x == -1) {
// magic sentinel value
break;
}
std::cout << "Received: " << x << std::endl;
}
}
catch (boost::interprocess::interprocess_exception& ex) {
std::cerr << ex.what() << std::endl;
return 1;
}
std::cout << "Finished server." << std::endl;
return 0;
}

swapcontext. What's meaning of field uc_stack in struct ucontext_t?Who use it? The coroutine or the coroutine's signal handler? How can I test it?

What's meaning of field uc_stack in struct ucontext_t?Who use it? The coroutine or the coroutine's signal handler? How can I test it? For example
#include <iostream>
#include <ucontext.h>
#include <queue>
#include <signal.h>
using namespace std;
void sigHandler(int signo)
{
printf("sigHandler:%x\n", &signo);
exit(-1);
}
queue<int> qProduct;
void consumer(ucontext_t* pConsumer, ucontext_t* pProducer)
{
char a[SIGSTKSZ] = {0};
while(1)
{
if(qProduct.size() > 0)
{
cout << __FUNCTION__ << "|" << qProduct.front() << endl;
qProduct.pop();
}
else
{
cout << pConsumer << "|" << pProducer << endl;
swapcontext(pConsumer, pProducer);
}
}
}
void producer(ucontext_t* pConsumer, ucontext_t* pProducer, bool* pFinished)
{
for(int i=0; i<10; i++)
{
if(qProduct.size() < 5)
{
qProduct.push(i);
cout << __FUNCTION__ << "|" << i << endl;
}
else
{
cout << pConsumer << "|P|" << pProducer << endl;
swapcontext(pProducer, pConsumer);
}
}
cout << pConsumer << "|P|" << pProducer << endl;
swapcontext(pProducer, pConsumer);
*pFinished = true;
}
int main(int argc, char* argv[])
{
ucontext_t Main, Consumer, Producer;
/* The stack for the iterator function. */
char consumer_stack[SIGSTKSZ];
char producer_stack[SIGSTKSZ];
cout << "SIGSTKSZ:" << SIGSTKSZ << endl;
/* Flag indicating that the iterator has completed. */
volatile bool bFinished = false;
getcontext(&Consumer);
Consumer.uc_link = &Main;
Consumer.uc_stack.ss_sp = consumer_stack;
Consumer.uc_stack.ss_size = sizeof(consumer_stack);
makecontext(&Consumer, (void (*)(void))consumer, 2, &Consumer, &Producer);
getcontext(&Producer);
Producer.uc_link = &Main;
Producer.uc_stack.ss_sp = producer_stack;
Producer.uc_stack.ss_size = sizeof(producer_stack);
makecontext(&Producer, (void (*)(void))producer, 3, &Consumer, &Producer, &bFinished);
if(!bFinished)
{
swapcontext(&Main, &Producer);
}
return 0;
}
Who use the stack "consumer_stack", "consumer" or "sigHandler"?How to prove it?