diff --git "a/src/OSD/OSD_Thread.cxx" "b/src/OSD/OSD_Thread.cxx"
index 6cb9716..74a58f0 100644
--- "a/src/OSD/OSD_Thread.cxx"	
+++ "b/src/OSD/OSD_Thread.cxx"	
@@ -13,6 +13,8 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <Standard_ErrorHandler.hxx>
+
 #include <OSD_Thread.hxx>
 
 //=============================================
@@ -66,6 +68,7 @@ void OSD_Thread::Assign (const OSD_Thread &other)
 #endif
 
   myThreadId = other.myThreadId;
+  myException = other.myException;
 }
 
 //=============================================
@@ -111,13 +114,24 @@ void OSD_Thread::SetFunction (const OSD_ThreadFunction &func)
 // On Windows the signature of the thread function differs from that on UNIX/Linux.
 // As we use the same definition of the thread function on all platforms (POSIX-like),
 // we need to introduce appropriate wrapper function on Windows.
-struct WNTthread_data { void *data; OSD_ThreadFunction func; };
+struct WNTthread_data { void *data; OSD_ThreadFunction func; std::shared_ptr<std::exception_ptr> exc; };
 static DWORD WINAPI WNTthread_func (LPVOID data)
 {
   WNTthread_data *adata = (WNTthread_data*)data;
-  void* ret = adata->func ( adata->data );
-  free ( adata );
-  return PtrToLong (ret);
+  DWORD ret = WAIT_OBJECT_0;
+
+  try {
+      OCC_CATCH_SIGNALS
+
+      ret = PtrToLong(adata->func ( adata->data ));
+  }
+  catch(...)
+  {
+      *adata->exc = std::current_exception();
+  }
+
+  delete ( adata );
+  return ret;
 }
 #endif
 
@@ -135,13 +149,16 @@ Standard_Boolean OSD_Thread::Run (const Standard_Address data,
   Detach();
 
 #ifdef _WIN32
-
   // allocate intermediate data structure to pass both data parameter and address
   // of the real thread function to Windows thread wrapper function
-  WNTthread_data *adata = (WNTthread_data*)malloc ( sizeof(WNTthread_data) );
+  WNTthread_data *adata = new WNTthread_data;
   if ( ! adata ) return Standard_False;
+
+  myException = std::make_shared<std::exception_ptr>();
+
   adata->data = data;
   adata->func = myFunc;
+  adata->exc = myException;
 
   // then try to create a new thread
 
@@ -151,7 +168,7 @@ Standard_Boolean OSD_Thread::Run (const Standard_Address data,
     SetThreadPriority (myThread, myPriority);
   else {
     memset ( adata, 0, sizeof(WNTthread_data) );
-    free ( adata );
+    delete ( adata );
   }
 
 #else
@@ -190,6 +207,7 @@ void OSD_Thread::Detach ()
 
   myThread = 0;
   myThreadId = 0;
+  myException = nullptr;
 }
 
 //=============================================
@@ -222,6 +240,12 @@ Standard_Boolean OSD_Thread::Wait (Standard_Address& theResult)
   CloseHandle (myThread);
   myThread   = 0;
   myThreadId = 0;
+
+  if(*myException != nullptr)
+  {
+      std::rethrow_exception(*myException);
+  }
+
   return Standard_True;
 #else
   // On Unix/Linux, join the thread
@@ -264,6 +288,12 @@ Standard_Boolean OSD_Thread::Wait (const Standard_Integer theTimeMs,
     CloseHandle (myThread);
     myThread   = 0;
     myThreadId = 0;
+
+    if(*myException != nullptr)
+    {
+        std::rethrow_exception(*myException);
+    }
+
     return Standard_True;
   }
   else if (ret == WAIT_TIMEOUT)
@@ -306,6 +336,12 @@ Standard_Boolean OSD_Thread::Wait (const Standard_Integer theTimeMs,
   #endif
     myThread   = 0;
     myThreadId = 0;
+
+    if(*myException != nullptr)
+    {
+        std::rethrow_exception(*myException);
+    }
+
     return Standard_True;
 #endif
 }
diff --git "a/src/OSD/OSD_Thread.hxx" "b/src/OSD/OSD_Thread.hxx"
index 527f440..c47ef02 100644
--- "a/src/OSD/OSD_Thread.hxx"	
+++ "b/src/OSD/OSD_Thread.hxx"	
@@ -16,6 +16,9 @@
 #ifndef _OSD_Thread_HeaderFile
 #define _OSD_Thread_HeaderFile
 
+#include <exception>
+#include <memory>
+
 #include <Standard.hxx>
 #include <Standard_DefineAlloc.hxx>
 #include <Standard_Handle.hxx>
@@ -120,6 +123,7 @@ private:
   OSD_PThread myThread;
   Standard_ThreadId myThreadId;
   Standard_Integer myPriority;
+  std::shared_ptr<std::exception_ptr> myException;
 
 };
