summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/m_system.h143
-rw-r--r--plugins/IEView/Utils.cpp4
-rw-r--r--plugins/Mir_core/miranda.cpp35
-rw-r--r--plugins/Mir_core/miranda.h2
-rw-r--r--plugins/Mir_core/utils.cpp2
-rw-r--r--protocols/GTalkExt/avatar.cpp4
-rw-r--r--src/core/miranda.cpp52
7 files changed, 43 insertions, 199 deletions
diff --git a/include/m_system.h b/include/m_system.h
index e8c22a9124..4cc9105773 100644
--- a/include/m_system.h
+++ b/include/m_system.h
@@ -133,149 +133,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MS_SYSTEM_REMOVEWAIT "Miranda/System/RemoveWait"
/*
-
- -- Thread Safety --
-
- Proper thread safe shutdown was implemented in 0.3.0.0 (2003/04/18)
- and not before, therefore it is improper that any MT plugins be used
- with earlier versions of Miranda (as hav0c will result)
-
- Note: This does not apply to MT plugins which included their own
- thread-safe shutdown routines.
-
- Shutdown thread safety works thusly:
-
- All new threads must call MS_SYSTEM_THREAD_PUSH and MS_SYSTEM_THREAD_POP
- when they return.
-
- Due to the nature of thread creation, it is illegal to assume
- just a call pair of MS_SYSTEM_THREAD_PUSH inside the thread will
- be enough -- the source thread may only return when the new child
- thread has actually executed MS_SYSTEM_THREAD_PUSH
-
- This is because a thread maybe in an undefined state at the point
- when the thread creation routine returns, thus Miranda may exit
- thinking it is safe to do so, because MS_SYSTEM_THREAD_PUSH was not
- called in time.
-
- See miranda.c for how this can be done using an event object
- which is signalled just after the MS_SYSTEM_THREAD_PUSH call is executed
- and so the source thread knows that the created thread is known to Miranda.
-
- -- What happens when Miranda exits --
-
- Miranda will firstly set an event object to signalled, this will
- make MS_SYSTEM_TERMINATED return TRUE, it will then fire ME_SYSTEM_PRESHUTDOWN
- at this point, no plugins or modules are unloaded.
-
- Miranda will then enumerate all active threads and queue an APC call
- to each thread, so any thread in an alertable state will become active,
- this functionailty may not be required by your threads: but if you use
- the Winsock2 event object system or Sleep() please use the alertable
- wait functions, so that the thread will 'wake up' when Miranda queues
- a message to it, SleepEx() will return WAIT_IO_COMPLETION if this happens.
-
- After all threads have been signalled, Miranda will spin on the unwind thread stack waiting
- for it to become empty, in this time, it will carry on processing thread
- switches, clearing it's own APC calls (used by NotifyEventHooks(), CallServiceSync())
-
- So a thread should be written in this kind of form:
-
- void mythread(void *arg)
- {
- // assume all thread pushing/popping is done by forkthread()
- int run=1;
- for (;run;)
- {
- Beep(4391, 500);
- SleepEx(1500, TRUE);
- if (Miranda_Terminated()) {
- Beep(5000, 150); run=0;
- } //if
- } //for
- }
-
- The above will make a nice Beep every 1.5 seconds and when the UI
- quits, it will make a lower beep and then return.
-
- As many copies of this thread maybe running, the creator does not need
- to worry about what to do with previous threads, as long as they're on the
- unwind stack.If there are any global resources (and they're mutex) you can free() them
- at Unload(), which will only be called, after all threads have returned.
-
- -- Summary --
-
- MS_SYSTEM_TERMINATED (will start returning TRUE)
- ME_SYSTEM_PRESHUTDOWN will be fired (The CList won't be visible at this point)
-
- All PROTOTYPE_PROTOCOL registered plugins will be sent ID_STATUS_OFFLINE
- automatically.
-
- All the threads will be notified via QueueUserAPC() and then Miranda
- will poll on the unwind thread queue until it is empty.
-
- ME_SYSTEM_SHUTDOWN will be fired, the database will be unloaded, the core
- will be unloaded -- Miranda will return.
-
-*/
-
-/* 0.5.2+
-wParam=function address
-lParam=function parameter
-
-registers a thread in the core and forks it
-
-*/
-
-#define MS_SYSTEM_FORK_THREAD "Miranda/Thread/Fork"
-
-/* 0.5.2+
-wParam=void* - thread owner object
-lParam=FORK_THREADEX_PARAMS*
-
-registers a thread in the core and forks it
-passes the extended parameters info and returns the thread id
-
-*/
-
-typedef struct
-{
- pThreadFuncEx pFunc;
- int iStackSize;
- void* arg;
- unsigned* threadID;
-}
- FORK_THREADEX_PARAMS;
-
-#define MS_SYSTEM_FORK_THREAD_EX "Miranda/Thread/ForkEx"
-
-/*
-wParam=0
-lParam=0
-
-Add a thread to the unwind wait stack that Miranda will poll on
-when it is tearing down modules.
-
-This must be called in the context of the thread that is to be pushed
-i.e. there are no args, it works out what thread is being called
-and gets itself a handle to the calling thread.
-
-*/
-#define MS_SYSTEM_THREAD_PUSH "Miranda/Thread/Push"
-
-/*
-wParam=0
-lParam=0
-
-Remove a thread from the unwind wait stack -- it is expected
-that the call be made in the context of the thread to be removed.
-
-Miranda will begin to tear down modules and plugins if/when the
-last thread from the unwind stack is removed.
-*/
-#define MS_SYSTEM_THREAD_POP "Miranda/Thread/Pop"
-
-/*
wParam=0
lParam=0
diff --git a/plugins/IEView/Utils.cpp b/plugins/IEView/Utils.cpp
index de2d02694b..fef1056cac 100644
--- a/plugins/IEView/Utils.cpp
+++ b/plugins/IEView/Utils.cpp
@@ -339,10 +339,10 @@ static void __cdecl forkthread_r(struct FORK_ARG *fa)
{
void (*callercode)(void*) = fa->threadcode;
void *arg = fa->arg;
- CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+ Thread_Push((HINSTANCE)callercode);
SetEvent(fa->hEvent);
callercode(arg);
- CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ Thread_Pop();
return;
}
diff --git a/plugins/Mir_core/miranda.cpp b/plugins/Mir_core/miranda.cpp
index 0ca0f4bd6c..067cff5d4c 100644
--- a/plugins/Mir_core/miranda.cpp
+++ b/plugins/Mir_core/miranda.cpp
@@ -85,7 +85,7 @@ void __cdecl forkthread_r(void * arg)
struct FORK_ARG * fa = (struct FORK_ARG *) arg;
void (*callercode)(void*)=fa->threadcode;
void * cookie=fa->arg;
- CallService(MS_SYSTEM_THREAD_PUSH, 0, (LPARAM)callercode);
+ Thread_Push(( HINSTANCE)callercode);
SetEvent(fa->hEvent);
__try
{
@@ -96,7 +96,7 @@ void __cdecl forkthread_r(void * arg)
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ Thread_Pop();
return;
}
@@ -127,7 +127,7 @@ unsigned __stdcall forkthreadex_r(void * arg)
void *owner = fa->owner;
unsigned long rc = 0;
- CallService(MS_SYSTEM_THREAD_PUSH, (WPARAM)fa->owner, (LPARAM)threadcode);
+ Thread_Push((HINSTANCE)threadcode, fa->owner);
SetEvent(fa->hEvent);
__try
{
@@ -141,7 +141,7 @@ unsigned __stdcall forkthreadex_r(void * arg)
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ Thread_Pop();
return rc;
}
@@ -278,6 +278,27 @@ MIR_CORE_DLL(void) Thread_Wait(void)
typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG);
#define ThreadQuerySetWin32StartAddress 9
+static void* GetCurrentThreadEntryPoint()
+{
+ LONG ntStatus;
+ HANDLE hDupHandle, hCurrentProcess;
+ DWORD_PTR dwStartAddress;
+
+ pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQueryInformationThread" );
+ if(NtQueryInformationThread == NULL) return 0;
+
+ hCurrentProcess = GetCurrentProcess();
+ if(!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)){
+ SetLastError(ERROR_ACCESS_DENIED);
+ return NULL;
+ }
+ ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), NULL);
+ CloseHandle(hDupHandle);
+
+ if(ntStatus != ERROR_SUCCESS) return 0;
+ return ( void* )dwStartAddress;
+}
+
MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner)
{
ResetEvent(hThreadQueueEmpty); // thread list is not empty
@@ -287,7 +308,11 @@ MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner)
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
p->dwThreadId = GetCurrentThreadId();
p->pObject = pOwner;
- p->hOwner = hInst;
+ if (pluginListAddr.getIndex(hInst) != -1)
+ p->hOwner = hInst;
+ else
+ p->hOwner = GetInstByAddress(( hInst != NULL ) ? (PVOID)hInst : GetCurrentThreadEntryPoint());
+
threads.insert(p);
ReleaseMutex(hStackMutex);
diff --git a/plugins/Mir_core/miranda.h b/plugins/Mir_core/miranda.h
index 9faa569eff..5e0a0d2fb1 100644
--- a/plugins/Mir_core/miranda.h
+++ b/plugins/Mir_core/miranda.h
@@ -77,6 +77,8 @@ struct THook
CRITICAL_SECTION csHook;
};
+extern LIST<HINSTANCE__> pluginListAddr;
+
/**** langpack.cpp *********************************************************************/
char* LangPackTranslateString(struct LangPackMuuid* pUuid, const char *szEnglish, const int W);
diff --git a/plugins/Mir_core/utils.cpp b/plugins/Mir_core/utils.cpp
index f0fcdcfa07..5adb7e1cc1 100644
--- a/plugins/Mir_core/utils.cpp
+++ b/plugins/Mir_core/utils.cpp
@@ -118,7 +118,7 @@ static int sttComparePlugins(const HINSTANCE__* p1, const HINSTANCE__* p2)
return (p1 < p2) ? -1 : 1;
}
-static LIST<HINSTANCE__> pluginListAddr(10, sttComparePlugins);
+LIST<HINSTANCE__> pluginListAddr(10, sttComparePlugins);
MIR_CORE_DLL(void) RegisterModule(HINSTANCE hInst)
{
diff --git a/protocols/GTalkExt/avatar.cpp b/protocols/GTalkExt/avatar.cpp
index 086a4641d1..1e55937a44 100644
--- a/protocols/GTalkExt/avatar.cpp
+++ b/protocols/GTalkExt/avatar.cpp
@@ -124,7 +124,7 @@ struct AVACHANGED {
VOID CALLBACK CallSetAvatar(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
- CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+ Thread_Push(0);
__try {
AVACHANGED *ach = (AVACHANGED*)lpParameter;
__try {
@@ -136,7 +136,7 @@ VOID CALLBACK CallSetAvatar(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
}
}
__finally {
- CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ Thread_Pop();
}
}
diff --git a/src/core/miranda.cpp b/src/core/miranda.cpp
index 7a463c05c6..7cd2e02962 100644
--- a/src/core/miranda.cpp
+++ b/src/core/miranda.cpp
@@ -101,27 +101,6 @@ static INT_PTR srvSetExceptionFilter(WPARAM, LPARAM lParam)
}
/////////////////////////////////////////////////////////////////////////////////////////
-// forkthread - starts a new thread
-
-static INT_PTR ForkThreadService(WPARAM wParam, LPARAM lParam)
-{
- return (INT_PTR)forkthread((pThreadFunc)wParam, 0, (void*)lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// forkthreadex - starts a new thread with the extended info and returns the thread id
-
-static INT_PTR ForkThreadServiceEx(WPARAM wParam, LPARAM lParam)
-{
- FORK_THREADEX_PARAMS* params = (FORK_THREADEX_PARAMS*)lParam;
- if (params == NULL)
- return 0;
-
- UINT threadID;
- return forkthreadex(NULL, params->iStackSize, params->pFunc, (void*)wParam, params->arg, params->threadID ? params->threadID : &threadID);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG);
#define ThreadQuerySetWin32StartAddress 9
@@ -133,15 +112,15 @@ INT_PTR MirandaIsTerminated(WPARAM, LPARAM)
static void __cdecl compactHeapsThread(void*)
{
- while ( !Miranda_Terminated())
- {
+ while ( !Miranda_Terminated()) {
HANDLE hHeaps[256];
DWORD hc;
SleepEx((1000*60)*5, TRUE); // every 5 minutes
hc=GetProcessHeaps(255, (PHANDLE)&hHeaps);
if (hc != 0 && hc < 256) {
DWORD j;
- for (j=0;j<hc;j++) HeapCompact(hHeaps[j], 0);
+ for (j=0; j < hc; j++)
+ HeapCompact(hHeaps[j], 0);
}
} //while
}
@@ -185,8 +164,7 @@ static int SystemShutdownProc(WPARAM, LPARAM)
#define MIRANDA_PROCESS_WAIT_STEPS (MIRANDA_PROCESS_WAIT_TIMEOUT/MIRANDA_PROCESS_WAIT_RESOLUTION)
static INT_PTR CALLBACK WaitForProcessDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
- switch (msg)
- {
+ switch (msg) {
case WM_INITDIALOG:
TranslateDialogDefault(hwnd);
SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
@@ -198,16 +176,14 @@ static INT_PTR CALLBACK WaitForProcessDlgProc(HWND hwnd, UINT msg, WPARAM wParam
case WM_TIMER:
if ( SendDlgItemMessage(hwnd, IDC_PROGRESSBAR, PBM_STEPIT, 0, 0) == MIRANDA_PROCESS_WAIT_STEPS)
EndDialog(hwnd, 0);
- if ( WaitForSingleObject((HANDLE)GetWindowLongPtr(hwnd, GWLP_USERDATA), 1) != WAIT_TIMEOUT)
- {
+ if ( WaitForSingleObject((HANDLE)GetWindowLongPtr(hwnd, GWLP_USERDATA), 1) != WAIT_TIMEOUT) {
SendDlgItemMessage(hwnd, IDC_PROGRESSBAR, PBM_SETPOS, MIRANDA_PROCESS_WAIT_STEPS, 0);
EndDialog(hwnd, 0);
}
break;
case WM_COMMAND:
- if ( HIWORD(wParam) == IDCANCEL)
- {
+ if ( HIWORD(wParam) == IDCANCEL) {
SendDlgItemMessage(hwnd, IDC_PROGRESSBAR, PBM_SETPOS, MIRANDA_PROCESS_WAIT_STEPS, 0);
EndDialog(hwnd, 0);
}
@@ -466,18 +442,6 @@ static INT_PTR RemoveWait(WPARAM wParam, LPARAM)
///////////////////////////////////////////////////////////////////////////////
-static INT_PTR UnwindThreadPush(WPARAM wParam, LPARAM lParam)
-{ Thread_Push((HINSTANCE)lParam, (void*)wParam);
- return 0;
-}
-
-static INT_PTR UnwindThreadPop(WPARAM, LPARAM)
-{ Thread_Pop();
- return 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
int LoadSystemModule(void)
{
hMirandaShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -488,10 +452,6 @@ int LoadSystemModule(void)
hModulesLoadedEvent = CreateHookableEvent(ME_SYSTEM_MODULESLOADED);
hOkToExitEvent = CreateHookableEvent(ME_SYSTEM_OKTOEXIT);
- CreateServiceFunction(MS_SYSTEM_FORK_THREAD, ForkThreadService);
- CreateServiceFunction(MS_SYSTEM_FORK_THREAD_EX, ForkThreadServiceEx);
- CreateServiceFunction(MS_SYSTEM_THREAD_PUSH, UnwindThreadPush);
- CreateServiceFunction(MS_SYSTEM_THREAD_POP, UnwindThreadPop);
CreateServiceFunction(MS_SYSTEM_TERMINATED, MirandaIsTerminated);
CreateServiceFunction(MS_SYSTEM_OKTOEXIT, OkToExit);
CreateServiceFunction(MS_SYSTEM_GETVERSION, GetMirandaVersion);