Use _beginthreadex instead of CreateThread

The documentation for ExitThread [1] has this comment:

  A thread in an executable that calls the C run-time library (CRT) should use
  the _beginthreadex and _endthreadex functions for thread management rather
  than CreateThread and ExitThread; this requires the use of the multithreaded
  version of the CRT. If a thread created using CreateThread calls the CRT,
  the CRT may terminate the process in low-memory conditions.

Since ~all our code uses CRT, be safe and use _beginthreadex.

[1] https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread

Change-Id: If3e566592e921b00240e08aa759d8cdbc421d44b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155513
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
Mike Kaganski 2023-08-09 14:29:54 +03:00
parent da54fbce1c
commit 8a0c43fa86
10 changed files with 37 additions and 38 deletions

View file

@ -18,6 +18,7 @@
*/ */
#include <systools/win32/uwinapi.h> #include <systools/win32/uwinapi.h>
#include <process.h>
#include <tlhelp32.h> #include <tlhelp32.h>
#include <rpc.h> #include <rpc.h>
#include <winsock.h> #include <winsock.h>
@ -159,7 +160,7 @@ static DWORD GetParentProcessId()
return dwParentProcessId; return dwParentProcessId;
} }
static DWORD WINAPI ParentMonitorThreadProc( LPVOID lpParam ) static unsigned __stdcall ParentMonitorThreadProc(void* lpParam)
{ {
DWORD_PTR dwParentProcessId = reinterpret_cast<DWORD_PTR>(lpParam); DWORD_PTR dwParentProcessId = reinterpret_cast<DWORD_PTR>(lpParam);
@ -196,8 +197,6 @@ BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID )
if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
{ {
DWORD dwThreadId = 0;
DWORD_PTR dwParentProcessId = static_cast<DWORD_PTR>(_wtol( szBuffer )); DWORD_PTR dwParentProcessId = static_cast<DWORD_PTR>(_wtol( szBuffer ));
if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId ) if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId )
@ -205,8 +204,8 @@ BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID )
// No error check, it works or it does not // No error check, it works or it does not
// Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx // Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx
HANDLE hThread HANDLE hThread
= CreateThread(nullptr, 0, ParentMonitorThreadProc, = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, ParentMonitorThreadProc,
reinterpret_cast<LPVOID>(dwParentProcessId), 0, &dwThreadId); reinterpret_cast<LPVOID>(dwParentProcessId), 0, nullptr));
// Note: calling CreateThread in DllMain is discouraged // Note: calling CreateThread in DllMain is discouraged
// but this is only done in the headless mode and in // but this is only done in the headless mode and in
// that case no other threads should be running at startup // that case no other threads should be running at startup

View file

@ -43,7 +43,7 @@ namespace {
typedef struct typedef struct
{ {
HANDLE m_hThread; /* OS-handle used for all thread-functions */ HANDLE m_hThread; /* OS-handle used for all thread-functions */
DWORD m_ThreadId; /* identifier for this thread */ unsigned m_ThreadId; /* identifier for this thread */
sal_Int32 m_nTerminationRequested; sal_Int32 m_nTerminationRequested;
oslWorkerFunction m_WorkerFunction; oslWorkerFunction m_WorkerFunction;
void* m_pData; void* m_pData;
@ -54,7 +54,7 @@ typedef struct
static oslThread oslCreateThread(oslWorkerFunction pWorker, void* pThreadData, sal_uInt32 nFlags); static oslThread oslCreateThread(oslWorkerFunction pWorker, void* pThreadData, sal_uInt32 nFlags);
static DWORD WINAPI oslWorkerWrapperFunction(_In_ LPVOID pData) static unsigned __stdcall oslWorkerWrapperFunction(void* pData)
{ {
osl_TThreadImpl* pThreadImpl= static_cast<osl_TThreadImpl*>(pData); osl_TThreadImpl* pThreadImpl= static_cast<osl_TThreadImpl*>(pData);
@ -89,13 +89,13 @@ static oslThread oslCreateThread(oslWorkerFunction pWorker,
pThreadImpl->m_pData= pThreadData; pThreadImpl->m_pData= pThreadData;
pThreadImpl->m_nTerminationRequested= 0; pThreadImpl->m_nTerminationRequested= 0;
pThreadImpl->m_hThread= CreateThread( pThreadImpl->m_hThread= reinterpret_cast<HANDLE>(_beginthreadex(
nullptr, /* no security */ nullptr, /* no security */
0, /* default stack-size */ 0, /* default stack-size */
oslWorkerWrapperFunction, /* worker-function */ oslWorkerWrapperFunction, /* worker-function */
pThreadImpl, /* provide worker-function with data */ pThreadImpl, /* provide worker-function with data */
nFlags, /* start thread immediately or suspended */ nFlags, /* start thread immediately or suspended */
&pThreadImpl->m_ThreadId); &pThreadImpl->m_ThreadId));
if(pThreadImpl->m_hThread == nullptr) if(pThreadImpl->m_hThread == nullptr)
{ {

View file

@ -426,7 +426,7 @@ static LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LP
} }
static DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ ) static unsigned __stdcall SystrayThread(void* /*lpParam*/)
{ {
osl_setThreadName("SystrayThread"); osl_setThreadName("SystrayThread");
@ -516,8 +516,8 @@ void win32_init_sys_tray()
nullptr // window-creation data nullptr // window-creation data
); );
DWORD dwThreadId; CloseHandle(reinterpret_cast<HANDLE>(
CloseHandle(CreateThread(nullptr, 0, SystrayThread, nullptr, 0, &dwThreadId)); _beginthreadex(nullptr, 0, SystrayThread, nullptr, 0, nullptr)));
} }
} }

View file

@ -43,6 +43,7 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
#include <Winhttp.h> #include <Winhttp.h>
#include <process.h>
#endif #endif
using namespace com::sun::star; using namespace com::sun::star;
@ -460,7 +461,7 @@ struct GetPACProxyData
// Tries to get proxy configuration using WinHttpGetProxyForUrl, which supports Web Proxy Auto-Discovery // Tries to get proxy configuration using WinHttpGetProxyForUrl, which supports Web Proxy Auto-Discovery
// (WPAD) protocol and manually configured address to get Proxy Auto-Configuration (PAC) file. // (WPAD) protocol and manually configured address to get Proxy Auto-Configuration (PAC) file.
// The WinINet/WinHTTP functions cannot correctly run in a STA COM thread, so use a dedicated thread // The WinINet/WinHTTP functions cannot correctly run in a STA COM thread, so use a dedicated thread
DWORD WINAPI GetPACProxyThread(_In_ LPVOID lpParameter) unsigned __stdcall GetPACProxyThread(void* lpParameter)
{ {
assert(lpParameter); assert(lpParameter);
GetPACProxyData* pData = static_cast<GetPACProxyData*>(lpParameter); GetPACProxyData* pData = static_cast<GetPACProxyData*>(lpParameter);
@ -557,7 +558,8 @@ InternetProxyServer GetPACProxy(const OUString& rProtocol, const OUString& rHost
} }
} }
HANDLE hThread = CreateThread(nullptr, 0, GetPACProxyThread, &aData, 0, nullptr); HANDLE hThread = reinterpret_cast<HANDLE>(
_beginthreadex(nullptr, 0, GetPACProxyThread, &aData, 0, nullptr));
if (hThread) if (hThread)
{ {
WaitForSingleObject(hThread, INFINITE); WaitForSingleObject(hThread, INFINITE);

View file

@ -54,7 +54,7 @@ class DropTarget : public cppu::BaseMutex,
{ {
private: private:
friend DWORD WINAPI DndTargetOleSTAFunc(LPVOID pParams); friend unsigned __stdcall DndTargetOleSTAFunc(void* pParams);
// The native window which acts as drop target. // The native window which acts as drop target.
// It is set in initialize. In case RegisterDragDrop fails it is set // It is set in initialize. In case RegisterDragDrop fails it is set
// to NULL // to NULL
@ -65,7 +65,7 @@ private:
DWORD m_threadIdWindow; DWORD m_threadIdWindow;
// This is the thread id of the OLE thread that is created in DropTarget::initialize // This is the thread id of the OLE thread that is created in DropTarget::initialize
// when the calling thread is an MTA // when the calling thread is an MTA
DWORD m_threadIdTarget; unsigned m_threadIdTarget;
// The handle of the thread that is created in DropTarget::initialize // The handle of the thread that is created in DropTarget::initialize
// when the calling thread is an MTA // when the calling thread is an MTA
HANDLE m_hOleThread; HANDLE m_hOleThread;

View file

@ -634,7 +634,7 @@ struct WorkerThreadData
#ifdef _WIN32 #ifdef _WIN32
static HANDLE hThreadID = nullptr; static HANDLE hThreadID = nullptr;
static DWORD WINAPI threadmain( _In_ LPVOID pArgs ) static unsigned __stdcall threadmain(void* pArgs)
{ {
OleInitialize( nullptr ); OleInitialize( nullptr );
static_cast<WorkerThreadData*>(pArgs)->pWorker( static_cast<WorkerThreadData*>(pArgs)->pThreadData ); static_cast<WorkerThreadData*>(pArgs)->pWorker( static_cast<WorkerThreadData*>(pArgs)->pThreadData );
@ -661,14 +661,13 @@ void CreateMainLoopThread( oslWorkerFunction pWorker, void * pThreadData )
#ifdef _WIN32 #ifdef _WIN32
// sal thread always call CoInitializeEx, so a system dependent implementation is necessary // sal thread always call CoInitializeEx, so a system dependent implementation is necessary
DWORD uThreadID; hThreadID = reinterpret_cast<HANDLE>(_beginthreadex(
hThreadID = CreateThread(
nullptr, // no security handle nullptr, // no security handle
0, // stacksize 0 means default 0, // stacksize 0 means default
threadmain, // thread worker function threadmain, // thread worker function
new WorkerThreadData( pWorker, pThreadData ), // arguments for worker function new WorkerThreadData( pWorker, pThreadData ), // arguments for worker function
0, // 0 means: create immediately otherwise use CREATE_SUSPENDED 0, // 0 means: create immediately otherwise use CREATE_SUSPENDED
&uThreadID ); // thread id to fill nullptr )); // thread id to fill
#else #else
hThreadID = osl_createThread( MainWorkerFunction, new WorkerThreadData( pWorker, pThreadData ) ); hThreadID = osl_createThread( MainWorkerFunction, new WorkerThreadData( pWorker, pThreadData ) );
#endif #endif

View file

@ -241,8 +241,8 @@ CMtaOleClipboard::CMtaOleClipboard( ) :
s_theMtaOleClipboardInst = this; s_theMtaOleClipboardInst = this;
m_hOleThread = CreateThread( m_hOleThread = reinterpret_cast<HANDLE>(_beginthreadex(
nullptr, 0, CMtaOleClipboard::oleThreadProc, this, 0, &m_uOleThreadId ); nullptr, 0, CMtaOleClipboard::oleThreadProc, this, 0, &m_uOleThreadId ));
OSL_ASSERT( nullptr != m_hOleThread ); OSL_ASSERT( nullptr != m_hOleThread );
// setup the clipboard changed notifier thread // setup the clipboard changed notifier thread
@ -253,9 +253,8 @@ CMtaOleClipboard::CMtaOleClipboard( ) :
m_hClipboardChangedNotifierEvents[1] = CreateEventW( nullptr, MANUAL_RESET, INIT_NONSIGNALED, nullptr ); m_hClipboardChangedNotifierEvents[1] = CreateEventW( nullptr, MANUAL_RESET, INIT_NONSIGNALED, nullptr );
OSL_ASSERT( nullptr != m_hClipboardChangedNotifierEvents[1] ); OSL_ASSERT( nullptr != m_hClipboardChangedNotifierEvents[1] );
DWORD uThreadId; m_hClipboardChangedNotifierThread = reinterpret_cast<HANDLE>(_beginthreadex(
m_hClipboardChangedNotifierThread = CreateThread( nullptr, 0, CMtaOleClipboard::clipboardChangedNotifierThreadProc, this, 0, nullptr ));
nullptr, 0, CMtaOleClipboard::clipboardChangedNotifierThreadProc, this, 0, &uThreadId );
OSL_ASSERT( nullptr != m_hClipboardChangedNotifierThread ); OSL_ASSERT( nullptr != m_hClipboardChangedNotifierThread );
} }
@ -675,7 +674,7 @@ unsigned int CMtaOleClipboard::run( )
return nRet; return nRet;
} }
DWORD WINAPI CMtaOleClipboard::oleThreadProc( _In_ LPVOID pParam ) unsigned __stdcall CMtaOleClipboard::oleThreadProc( void* pParam )
{ {
osl_setThreadName("CMtaOleClipboard::run()"); osl_setThreadName("CMtaOleClipboard::run()");
@ -686,7 +685,7 @@ DWORD WINAPI CMtaOleClipboard::oleThreadProc( _In_ LPVOID pParam )
return pInst->run( ); return pInst->run( );
} }
DWORD WINAPI CMtaOleClipboard::clipboardChangedNotifierThreadProc( _In_ LPVOID pParam ) unsigned __stdcall CMtaOleClipboard::clipboardChangedNotifierThreadProc(void* pParam)
{ {
osl_setThreadName("CMtaOleClipboard::clipboardChangedNotifierThreadProc()"); osl_setThreadName("CMtaOleClipboard::clipboardChangedNotifierThreadProc()");
CMtaOleClipboard* pInst = static_cast< CMtaOleClipboard* >( pParam ); CMtaOleClipboard* pInst = static_cast< CMtaOleClipboard* >( pParam );

View file

@ -75,15 +75,15 @@ private:
LRESULT onClipboardUpdate(); LRESULT onClipboardUpdate();
static LRESULT CALLBACK mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); static LRESULT CALLBACK mtaOleReqWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
static DWORD WINAPI oleThreadProc( _In_ LPVOID pParam ); static unsigned __stdcall oleThreadProc(void* pParam);
static DWORD WINAPI clipboardChangedNotifierThreadProc( _In_ LPVOID pParam ); static unsigned __stdcall clipboardChangedNotifierThreadProc(void* pParam);
bool WaitForThreadReady( ) const; bool WaitForThreadReady( ) const;
private: private:
HANDLE m_hOleThread; HANDLE m_hOleThread;
DWORD m_uOleThreadId; unsigned m_uOleThreadId;
HANDLE m_hEvtThrdReady; HANDLE m_hEvtThrdReady;
HWND m_hwndMtaOleReqWnd; HWND m_hwndMtaOleReqWnd;
HANDLE m_hEvtWndDisposed; HANDLE m_hEvtWndDisposed;

View file

@ -48,7 +48,7 @@ using namespace com::sun::star::awt::MouseButton;
using namespace com::sun::star::awt; using namespace com::sun::star::awt;
using namespace com::sun::star::lang; using namespace com::sun::star::lang;
static DWORD WINAPI DndOleSTAFunc(_In_ LPVOID pParams); static unsigned __stdcall DndOleSTAFunc(void* pParams);
DragSource::DragSource( const Reference<XComponentContext>& rxContext): DragSource::DragSource( const Reference<XComponentContext>& rxContext):
WeakComponentImplHelper< XDragSource, XInitialization, XServiceInfo >(m_aMutex), WeakComponentImplHelper< XDragSource, XInitialization, XServiceInfo >(m_aMutex),
@ -120,8 +120,8 @@ void DragSource::StartDragImpl(
// The thread accesses members of this instance but does not call acquire. // The thread accesses members of this instance but does not call acquire.
// Hopefully this instance is not destroyed before the thread has terminated. // Hopefully this instance is not destroyed before the thread has terminated.
DWORD threadId; HANDLE hThread
HANDLE hThread = CreateThread(nullptr, 0, DndOleSTAFunc, this, 0, &threadId); = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, DndOleSTAFunc, this, 0, nullptr));
// detach from thread // detach from thread
CloseHandle(hThread); CloseHandle(hThread);
@ -304,7 +304,7 @@ dtrans_DragSource_get_implementation(
carries out a drag and drop operation by calling carries out a drag and drop operation by calling
DoDragDrop. The thread also notifies all DoDragDrop. The thread also notifies all
XSourceListener. */ XSourceListener. */
DWORD WINAPI DndOleSTAFunc(_In_ LPVOID pParams) unsigned __stdcall DndOleSTAFunc(void* pParams)
{ {
osl_setThreadName("DragSource DndOleSTAFunc"); osl_setThreadName("DragSource DndOleSTAFunc");

View file

@ -44,7 +44,7 @@ using namespace com::sun::star::datatransfer::dnd::DNDConstants;
#define WM_REGISTERDRAGDROP WM_USER + 1 #define WM_REGISTERDRAGDROP WM_USER + 1
#define WM_REVOKEDRAGDROP WM_USER + 2 #define WM_REVOKEDRAGDROP WM_USER + 2
DWORD WINAPI DndTargetOleSTAFunc(LPVOID pParams); unsigned __stdcall DndTargetOleSTAFunc(void* pParams);
DropTarget::DropTarget( const Reference<XComponentContext>& rxContext): DropTarget::DropTarget( const Reference<XComponentContext>& rxContext):
WeakComponentImplHelper<XInitialization,XDropTarget, XServiceInfo>(m_aMutex), WeakComponentImplHelper<XInitialization,XDropTarget, XServiceInfo>(m_aMutex),
@ -146,8 +146,8 @@ void SAL_CALL DropTarget::initialize( const Sequence< Any >& aArguments )
// It indicates that the thread is ready to receive messages. // It indicates that the thread is ready to receive messages.
HANDLE m_evtThreadReady= CreateEventW( nullptr, FALSE, FALSE, nullptr); HANDLE m_evtThreadReady= CreateEventW( nullptr, FALSE, FALSE, nullptr);
m_hOleThread= CreateThread( nullptr, 0, DndTargetOleSTAFunc, m_hOleThread = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, DndTargetOleSTAFunc,
&m_evtThreadReady, 0, &m_threadIdTarget); &m_evtThreadReady, 0, &m_threadIdTarget));
WaitForSingleObject( m_evtThreadReady, INFINITE); WaitForSingleObject( m_evtThreadReady, INFINITE);
CloseHandle( m_evtThreadReady); CloseHandle( m_evtThreadReady);
PostThreadMessageW( m_threadIdTarget, WM_REGISTERDRAGDROP, reinterpret_cast<WPARAM>(this), 0); PostThreadMessageW( m_threadIdTarget, WM_REGISTERDRAGDROP, reinterpret_cast<WPARAM>(this), 0);
@ -190,7 +190,7 @@ void SAL_CALL DropTarget::initialize( const Sequence< Any >& aArguments )
// This function is called as extra thread from DragSource::startDrag. // This function is called as extra thread from DragSource::startDrag.
// The function carries out a drag and drop operation by calling // The function carries out a drag and drop operation by calling
// DoDragDrop. The thread also notifies all XSourceListener. // DoDragDrop. The thread also notifies all XSourceListener.
DWORD WINAPI DndTargetOleSTAFunc(LPVOID pParams) unsigned __stdcall DndTargetOleSTAFunc(void* pParams)
{ {
osl_setThreadName("DropTarget DndTargetOleSTAFunc"); osl_setThreadName("DropTarget DndTargetOleSTAFunc");