Skip to content
Snippets Groups Projects
Commit 61d8b5eb authored by Federico's avatar Federico
Browse files

Implement pthread_exit, disabled by default

parent 1150aea6
Branches
No related tags found
No related merge requests found
......@@ -251,6 +251,23 @@ const unsigned char MAIN_PRIORITY=1;
const unsigned int MAX_TIME_SLICE=1000000;
#endif //SCHED_TYPE_PRIORITY
/// pthread_exit() is a dangerous function. To understand why, let's first
/// discuss how Linux implements it. On the surface, it looks like it neatly
/// works with C++ as it is implemented by throwing a special ForcedUnwind
/// exception thus calling C++ destructors. However, implementers left a number
/// of unhandled corner cases all leading to unexpected program termination.
/// These are: calling pthread_exit() from code that directly or indirectly...
/// 1) contains a catch(...) that does not rethrow? std::abort() gets called
/// 2) contains a function declared noexcept? std::abort() gets called
/// 3) is called from a destructor? you guessed it, std::abort() again!
/// For this reason pthread_exit() support is by default disabled in Miosix and
/// attempting to call this function is met with a linking error. If you really
/// need it, uncomment the line below. Oh, right, how does Miosix implement it?
/// Throwing a standard C++ exception, so a catch(...) can stop a pthread_exit()
/// which is imho neither better nor worse than Linux.
/// Reference: https://udrepper.livejournal.com/21541.html
//#define WITH_PTHREAD_EXIT
/// Enable support for pthread_key_create/pthread_key_delete/pthread_getspecific
//#define WITH_PTHREAD_KEYS
......
......@@ -38,6 +38,7 @@
#include "filesystem/file_access.h"
#include "error.h"
#include "logging.h"
#include "pthread_private.h"
// settings for miosix
#include "config/miosix_settings.h"
#include "util/util.h"
......@@ -150,11 +151,15 @@ void *mainLoader(void *argv)
#else //__NO_EXCEPTIONS
try {
main(0,NULL);
#ifdef WITH_PTHREAD_EXIT
} catch(PthreadExitException&) {
errorLog("***Attempting to pthread_exit from main\n");
#endif //WITH_PTHREAD_EXIT
} catch(std::exception& e) {
errorLog("***An exception propagated through a thread\n");
errorLog("***An exception propagated through main\n");
errorLog("what():%s\n",e.what());
} catch(...) {
errorLog("***An exception propagated through a thread\n");
errorLog("***An exception propagated through main\n");
}
#endif //__NO_EXCEPTIONS
......
......@@ -830,6 +830,10 @@ void Thread::threadLauncher(void *(*threadfunc)(void*), void *argv)
#else //__NO_EXCEPTIONS
try {
result=threadfunc(argv);
#ifdef WITH_PTHREAD_EXIT
} catch(PthreadExitException& e) {
result=e.getReturnValue();
#endif //WITH_PTHREAD_EXIT
} catch(std::exception& e) {
errorLog("***An exception propagated through a thread\n");
errorLog("what():%s\n",e.what());
......
......@@ -390,6 +390,15 @@ int pthread_once(pthread_once_t *once, void (*func)())
int pthread_setcancelstate(int state, int *oldstate) { return 0; } //Stub
#ifdef WITH_PTHREAD_EXIT
void pthread_exit(void *returnValue)
{
throw PthreadExitException(returnValue);
}
#endif //WITH_PTHREAD_EXIT
#ifdef WITH_PTHREAD_KEYS
typedef void (*destructor_type)(void *);
......
......@@ -167,6 +167,35 @@ static inline unsigned int IRQdoMutexUnlockAllDepthLevels(pthread_mutex_t *mutex
return result;
}
#ifdef WITH_PTHREAD_EXIT
/**
* Exception type thrown when pthread_exit is called.
*
* NOTE: This type should not derive from std::exception on purpose, as it would
* be bad if a \code catch(std::exception& e) \endcode would match this
* exception.
*/
class PthreadExitException
{
public:
/**
* Constructor
* \param returnValue thread return value passed to pthread_exit
*/
PthreadExitException(void *returnValue) : returnValue(returnValue) {}
/**
* \return the thread return value passed to pthread_exit
*/
void *getReturnValue() const { return returnValue; }
private:
void *returnValue;
};
#endif //WITH_PTHREAD_EXIT
#ifdef WITH_PTHREAD_KEYS
/**
* Called at thread exit to call destructors for pthread keys
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment