Here is my program just to find the difference between pthread_exit and return from a thread.
struct foo{
int a,b,c,d;
~foo(){cout<<"foo destructor called"<<endl;}
};
//struct foo foo={1,2,3,4};
void printfoo(const char *s, const struct foo *fp)
{
cout<<s;
cout<<"struct at 0x"<<(unsigned)fp<<endl;
cout<<"foo.a="<<fp->a<<endl;
cout<<"foo.b="<<fp->b<<endl;
cout<<"foo.c="<<fp->c<<endl;
cout<<"foo.d="<<fp->d<<endl;
}
void *thr_fn1(void *arg)
{
struct foo foo={1,2,3,4};
printfoo("thread1:\n",&foo);
pthread_exit((void *)&foo);
//return((void *)&foo);
}
int main(int argc, char *argv[])
{
int err;
pthread_t tid1,tid2;
struct foo *fp;
err=pthread_create(&tid1,NULL,thr_fn1,NULL);
if(err!=0)
cout<<"can't create thread 1"<<endl;
err=pthread_join(tid1,(void **)&fp);
if(err!=0)
cout<<"can't join with thread 1"<<endl;
exit(0);
}
In "*thr_fn1" thread function I created an object foo.
According to the site pthread_exit vs. return
when I exit the thread function "thr_fun1()" using "return((void *)&foo);" it should call the destructor for the object foo, but it should not call the destructor when I call "pthread_exit((void *)&foo);" to return to main from function "thr_fun1()".
But in both the cases using "return((void *)&foo);" or "pthread_exit((void *)&foo);" the local object "foo" in function "thr_fun1()" is getting called.
This is not the behaviour I guess. Destructor should be called only in "return((void *)&foo);" case only.
Please verify me if I am wrong?
Your code has a serious problem. Specifically, you're using a local variable as the exit value for pthread_exit():
void *thr_fn1(void *arg)
{
struct foo foo={1,2,3,4};
printfoo("thread1:\n",&foo);
pthread_exit((void *)&foo);
//return((void *)&foo);
}
Per the Pthreads spec, "After a thread has terminated, the result of access to local (auto) variables of the thread is undefined."
Therefore, returning the address of a stack-allocated variable from your thread function as the thread exit value (in your case, pthread_exit((void *)&foo) ) will cause problems for any code that retrieves and attempts to dereference this address.
Yes, that's right. pthread_exit() immediately exits the current thread, without calling any destructors of objects higher up on the stack. If you're coding in C++, you should make sure to either always return from your thread procedure, or only call pthread_exit() from one of the bottommost stack frames with no objects with destructors still alive in that frame or any higher frames; otherwise, you will leak resources or cause other bad problems.
pthread_exit() is throwing an exception which causes the stack to unwind and destructors to be called for locals. See https://stackoverflow.com/a/11452942/12711 for more details.
The exception thrown is of type abi::__forced_unwind (from cxxabi.h); an Internet search can give you more details.
note: as other answers/comments have mentioned, returning the address of a local wouldn't work anyway, but that is besides the point of the question. You get the same behavior regarding destructing foo if some other valid address (or the null pointer) is returned instead of &foo.
Related
I'm reading the source code of a project, which is developed with C++98 on Linux.
There is such a piece of code:
class Test {
public:
Test();
static void func(void *arg) {
pthread_detach(pthread_self());
Test *obj = (Test*)arg;
// do something
}
};
Test::Test() {
pthread_t tid; // ???
pthread_create(&tid, NULL, Test::func, this);
}
This is quite clear: a thread is created in the constructor of Test, which calls the function func, and this thread would be detached.
But I'm worrying about pthread_t tid;. When the construcor returns, the variable tid, as a local variable, should be released. Am I right? However, we have passed its address as the first parameter of pthread_create.
Will it cause some lifetime issue, such as a segment fault?
When you call pthread_create, it saves the ID of the thread in tid.
It doesn't save the address of tid. It just puts the ID there before it returns.
So there is no problem.
However, if this bothers you, you should call pthread_detach(tid) in Test::Test instead of pthread_detach(pthread_self()) inside the thread.
It is allowed for a thread to detach itself, but it is slightly strange, because the purpose of pthread_detach is to tell the system that nobody is going to wait for this thread (by calling pthread_join), so the thread can be destroyed as soon as it finishes. Usually, whoever is creating the thread decides whether to wait for it or not - not the thread itself.
suppose I do the following :
void functionA(const char const input, int size)
{
char* dummyData = new char[size] ;
thread t(&functionB, dummyData);
t.detach();
}
void functionB(const char* data)
{
thread t2(&expendsiveFunction, data);
t2.join();
}
void expendsiveFunction(const char* data)
{
//do some expendsive stuff
delete[] data;
}
void main()
{
char* dataFromExternalSource; //lets assume this was provided from by an external soruce receive via TCP
functionA(dataFromExternalSource);
//do other stuff
}
I want the main thread to be available to do other stuff while I let the detached thread do the hard labour, in this scenario, am I right to say that dummyData will not go out of scope until expendsiveFunction() finishes?
any advise/comment would be helpful.
question 2: so even if i dont use thread.join() in function B, thread t will terminate at the end of expendsiveFunction() if functionB() just calls expendsiveFunction() ? (if functionB is part of another class..)
I'd say you are not right, since local variable dummyData goes out of scope when functionA finishes, and functionA will not wait for any other function or thread to finish.
The memory to which dummyData points, however, will remain valid since you allocate it dynamically using new[]. This memory is on the heap, and it will never "go out of scope" as it will never be popped from the stack; it will remain valid until you call delete[] somewhere in your code.
Note that only functionB and expensiveFunction hold a reference to this memory, so these functions are the only ones which can free this memory; if they don't, then you will have a memory leak.
BTW: your code does not compile; but that's not the question here.
Lets say i have a thread that is being created and detached on the stack like this:
void foo()
{
while(true){};
}
void runThread()
{
std::thread t(foo);
t.detach();
}
int main()
{
runThread();
}
The program means nothing of course, But what happens after we detach and exit runThred ? it was allocated on the stack so basically t will be destroyed after we exit runThred, but the thread itself will go on running regardless to the main thread because it is detached.
Is the best practice in such an example is to create it on the heap and save a pointer to it doing whatever (dcor) after that?
Or it means nothing if the t variable is destructed and we should just "ignore" it?
The std::thread object represents a handle to the thread through which it can be operated on. But once you call detach there is no connection between the object and the actual thread of execution.
As per pthread_key_create man page we can associate a destructor to be called at thread shut down. My problem is that the destructor function I have registered is not being called. Gist of my code is as follows.
static pthread_key_t key;
static pthread_once_t tls_init_flag = PTHREAD_ONCE_INIT;
void destructor(void *t) {
// thread local data structure clean up code here, which is not getting called
}
void create_key() {
pthread_key_create(&key, destructor);
}
// This will be called from every thread
void set_thread_specific() {
ts = new ts_stack; // Thread local data structure
pthread_once(&tls_init_flag, create_key);
pthread_setspecific(key, ts);
}
Any idea what might prevent this destructor being called? I am also using atexit() at moment to do some cleanup in the main thread. Is there any chance that is interfering with destructor function being called? I tried removing that as well. Still didn't work though. Also I am not clear if I should handle the main thread as a separate case with atexit. (It's a must to use atexit by the way, since I need to do some application specific cleanup at application exit)
This is by design.
The main thread exits (by returning or calling exit()), and that doesn't use pthread_exit(). POSIX documents pthread_exit calling the thread-specific destructors.
You could add pthread_exit() at the end of main. Alternatively, you can use atexit to do your destruction. In that case, it would be clean to set the thread-specific value to NULL so in case the pthread_exit was invoked, the destruction wouldn't happen twice for that key.
UPDATE Actually, I've solved my immediate worries by simply adding this to my global unit test setup function:
::atexit([] { ::pthread_exit(0); });
So, in context of my global fixture class MyConfig:
struct MyConfig {
MyConfig() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
::atexit([] { ::pthread_exit(0); });
}
~MyConfig() { google::protobuf::ShutdownProtobufLibrary(); }
};
Some of the references used:
http://www.resolvinghere.com/sof/6357154.shtml
https://sourceware.org/ml/pthreads-win32/2008/msg00007.html
http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_key_create.html
http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_exit.html
PS. Of course c++11 introduced <thread> so you have better and more portable primitves to work with.
It's already in sehe's answer, just to present the key points in a compact way:
pthread_key_create() destructor calls are triggered by a call to pthread_exit().
If the start routine of a thread returns, the behaviour is as if pthread_exit() was called (i. e., destructor calls are triggered).
However, if main() returns, the behaviour is as if exit() was called — no destructor calls are triggered.
This is explained in http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html. See also C++17 6.6.1p5 or C11 5.1.2.2.3p1.
I wrote a quick test and the only thing I changed was moving the create_key call of yours outside of the set_thread_specific.
That is, I called it within the main thread.
I then saw my destroy get called when the thread routine exited.
I call destructor() manually at the end of main():
void * ThreadData = NULL;
if ((ThreadData = pthread_getspecific(key)) != NULL)
destructor(ThreadData);
Of course key should be properly initialized earlier in main() code.
PS. Calling Pthread_Exit() at the end to main() seems to hang entire application...
Your initial thought of handling the main thread as a separate case with atexit worked best for me.
Be ware that pthread_exit(0) overwrites the exit value of the process. For example, the following program will exit with status of zero even though main() returns with number three:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
class ts_stack {
public:
ts_stack () {
printf ("init\n");
}
~ts_stack () {
printf ("done\n");
}
};
static void cleanup (void);
static pthread_key_t key;
static pthread_once_t tls_init_flag = PTHREAD_ONCE_INIT;
void destructor(void *t) {
// thread local data structure clean up code here, which is not getting called
delete (ts_stack*) t;
}
void create_key() {
pthread_key_create(&key, destructor);
atexit(cleanup);
}
// This will be called from every thread
void set_thread_specific() {
ts_stack *ts = new ts_stack (); // Thread local data structure
pthread_once(&tls_init_flag, create_key);
pthread_setspecific(key, ts);
}
static void cleanup (void) {
pthread_exit(0); // <-- Calls destructor but sets exit status to zero as a side effect!
}
int main (int argc, char *argv[]) {
set_thread_specific();
return 3; // Attempt to exit with status of 3
}
I had similar issue as yours: pthread_setspecific sets a key, but the destructor never gets called. To fix it we simply switched to thread_local in C++. You could also do something like if that change is too complicated:
For example, assume you have some class ThreadData that you want some action to be done on when the thread finishes execution. You define the destructor something on these lines:
void destroy_my_data(ThreadlData* t) {
delete t;
}
When your thread starts, you allocate memory for ThreadData* instance and assign a destructor to it like this:
ThreadData* my_data = new ThreadData;
thread_local ThreadLocalDestructor<ThreadData> tld;
tld.SetDestructorData(my_data, destroy_my_data);
pthread_setspecific(key, my_data)
Notice that ThreadLocalDestructor is defined as thread_local. We rely on C++11 mechanism that when the thread exits, the destructor of ThreadLocalDestructor will be automatically called, and ~ThreadLocalDestructor is implemented to call function destroy_my_data.
Here is the implementation of ThreadLocalDestructor:
template <typename T>
class ThreadLocalDestructor
{
public:
ThreadLocalDestructor() : m_destr_func(nullptr), m_destr_data(nullptr)
{
}
~ThreadLocalDestructor()
{
if (m_destr_func) {
m_destr_func(m_destr_data);
}
}
void SetDestructorData(void (*destr_func)(T*), T* destr_data)
{
m_destr_data = destr_data;
m_destr_func = destr_func;
}
private:
void (*m_destr_func)(T*);
T* m_destr_data;
};
It is my understanding that the function called when starting a thread inside an object should not be a class member. The best approach seems to be to launch a friend function, which gets you access back into your object.
In general, the member function (and therefore, the parent thread) that launched the daughter thread can continue or it can return. In every case where I use this technique, I let the launcher method just return to the app in the parent thread that called it; something like Qt threads.
When the daughter thread has finished its work, the final thing it does is return into the friend function which itself returns to something waiting to catch its return (pthread_koin or WaitForSingleEvent) or, if there is no catcher, I guess you'd say it returns to nowhere.
So, here is the question. If there is no catcher for the return from the friend function, that is, the parent thread is not in a member function, can I safely destroy the object that launched the child thread from the friend function?
EDIT --------------------------------------------------------------------------
Obvious from the responses, I need an example. We'll go for Windows. Not that different from Linux. I have left out lots of stuff, the class definition, etc.
Main creates so, a SomeObject on the heap.
Main calls so->run() and goes off to do other stuff.
Run() launches the daughter thread that runs SomeFriend().
SomeFriend() calls so->Worker() (that == so)
Worker() does whatever and returns to SomeFriend().
CAN I DELETE so HERE? i.e. delete that <<<=== the subject of this question.
SomeFriend() returns terminating the daughter thread.
//=================================================================
int main( int argc, char** argv )
{
SomeObject* so = new SomeObject();
so->run();
while(1)
{
DoOtherTasks(); // but don't exit!
}
return 0;
//=================================================================
void SomeObject::run();
(
volatile DWORD ThreadId; // Thread ID
HANDLE threadHandle;
try
{
threadHandle = CreateThread(
NULL, // default security attributes
0, // set stack size: default = 0
(LPTHREAD_START_ROUTINE)(SomeFriend),
(LPVOID*)this, // func args: this
0, // default creation flags
(LPDWORD)(&ThreadId) // ptr to thread identifier
);
}
catch ( ... )
{ throw; }
} // launches the thread and returns.
//=================================================================
void* SomeFriend( void* thisPtr ) // is a friend of SomeObject
{
SomeObject* that ((SomeObject*)thisPtr);
that->Worker();
// HERE IS WHERE THE QUESTION IS TALKING ABOUT
// CAN I DO THIS SAFELY?
delete that;
return (void*)NULL;
}
//=================================================================
void SomeObject::Worker() // remember, this is run in the daughter thread.
{
// whatever
return (void*)NULL;
}
To answer your edited question, yes you can delete that; However, remember that main() or any functions it calls might not have a valid so at any point in its logic after so->run() was called because of the way the thread scheduler may have scheduled the threads.
Think of the thread as "owning" so after you've called so->run(). main() and its stack descendants should never touch so again without guarded logic.
Yes.
Your memory management code should be thread-safe already (or threading would be dangerous to start with!) so the free() itself should be fine. The destruction is fine as well, as long as you keep in mind that nobody else may have a reference to this object as they will be pointing to a destructed object.
The reason that people say that it should not be a class member is that member functions have a typically hidden pointer that's also treated differently on a byte level from other parameters, so you can't just call it as a normal function with an extra parameter. This makes it typically incompatible with the pthread_create and CreateThreadEx functions that have a specific calling convention they want. That's why you have a bouncer static / global / friend function that does this calling convention conversion for you (and probably so transparently that you don't notice it yourself).
There's no inherent reason for not launching a member function as the top-level function in a thread. C++11 handles it just fine:
struct S {
void f();
};
S s;
int main() {
std::thread thr(&S::f, s);
thr.join();
return 0;
}