Skip to content

Commit 5809d3a

Browse files
Merge 04a2ed2 into f308a0d
2 parents f308a0d + 04a2ed2 commit 5809d3a

3 files changed

Lines changed: 64 additions & 2 deletions

File tree

nvdaHelper/remote/injection.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ DWORD WINAPI inprocMgrThreadFunc(LPVOID data) {
162162
return 0;
163163
}
164164
nhAssert(dllHandle==tempHandle);
165+
// Flush any log messages from other threads queued before the manager thread was started.
166+
log_flushQueue();
165167
//Register for all winEvents in this process.
166168
inprocWinEventHookID=SetWinEventHook(EVENT_MIN,EVENT_MAX,dllHandle,inproc_winEventCallback,GetCurrentProcessId(),0,WINEVENT_INCONTEXT);
167169
if(inprocWinEventHookID==0) {
@@ -240,6 +242,8 @@ DWORD WINAPI inprocMgrThreadFunc(LPVOID data) {
240242
// Unregister inproc winEvent callback
241243
UnhookWinEvent(inprocWinEventHookID);
242244
inprocWinEventHookID=0;
245+
// Flush any remaining log messages to NVDA
246+
log_flushQueue();
243247
//Release and close the thread mutex
244248
ReleaseMutex(threadMutex);
245249
CloseHandle(threadMutex);

nvdaHelper/remote/log.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,68 @@ This license can be found at:
1212
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
1313
*/
1414

15+
#include <string>
16+
#include <queue>
17+
#include <mutex>
1518
#include <crtdbg.h>
1619
#include "nvdaControllerInternal.h"
20+
#include "nvdaHelperRemote.h"
1721
#include <common/log.h>
1822

23+
std::deque<std::tuple<int, std::wstring>> logQueue;
24+
std::mutex logQueueLock;
25+
26+
// Fetch all available messages from the queue
27+
// and send them onto NvDA via rpc.
28+
void log_flushQueue() {
29+
// Ensure this is never called from outside the manager thread.
30+
if(
31+
!inprocMgrThreadHandle
32+
|| GetCurrentThreadId() != GetThreadId(inprocMgrThreadHandle)
33+
) {
34+
QueueUserAPC(log_flushQueue_apcFunc, inprocMgrThreadHandle, 0);
35+
return;
36+
}
37+
std::deque<std::tuple<int, std::wstring>> tempQueue;
38+
{
39+
std::lock_guard lock{logQueueLock};
40+
tempQueue.swap(logQueue);
41+
}
42+
for(auto& [level, msg] : tempQueue) {
43+
nvdaControllerInternal_logMessage(level, GetCurrentProcessId(), msg.c_str());
44+
}
45+
46+
}
47+
48+
void __stdcall log_flushQueue_apcFunc(ULONG_PTR data) {
49+
log_flushQueue();
50+
}
51+
1952
void logMessage(int level, const wchar_t* msg) {
20-
if(level>LOGLEVEL_DEBUG) nvdaControllerInternal_logMessage(level,GetCurrentProcessId(),msg);
53+
// Always log to any connected debugger
2154
OutputDebugString(msg);
55+
if(
56+
!inprocMgrThreadHandle
57+
|| GetCurrentThreadId() != GetThreadId(inprocMgrThreadHandle)
58+
) {
59+
// either the NVDA inproc manager thread is not yet running,
60+
// Or this message is being logged from outside NVDA's inproc manager thread.
61+
// So as to not block any app threads,
62+
// The message is queued for later fetching by NVDA's inproc manager thread
63+
{
64+
std::lock_guard lock{logQueueLock};
65+
logQueue.emplace_back(level, msg);
66+
}
67+
if(inprocMgrThreadHandle) {
68+
QueueUserAPC(log_flushQueue_apcFunc, inprocMgrThreadHandle, 0);
69+
}
70+
} else {
71+
// The message is being logged from NVDA's inproc manager thread.
72+
// Log to NVDA via rpc directly.
73+
// But first flush any pending log messages from other threads to ensure they are kept in the right order
74+
log_flushQueue();
75+
nvdaControllerInternal_logMessage(level,GetCurrentProcessId(),msg);
76+
}
2277
}
2378

2479
int NVDALogCrtReportHook(int reportType,const wchar_t *message,int *returnValue) {
@@ -38,4 +93,3 @@ int NVDALogCrtReportHook(int reportType,const wchar_t *message,int *returnValue)
3893
*returnValue=0;
3994
return true;
4095
}
41-

nvdaHelper/remote/nvdaHelperRemote.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,8 @@ bool unregisterWindowsHook(int hookType, HOOKPROC hookProc);
6969
// The handle for NVDA's inproc manager thread
7070
extern HANDLE inprocMgrThreadHandle;
7171

72+
// Flushes any remaining log messages to NVDA.
73+
// This should only be called from the NVDA inproc manager thread as it blocks while sending to NVDA.
74+
void log_flushQueue();
75+
7276
#endif

0 commit comments

Comments
 (0)