Hello,
I have a main application (Main.exe) that calls CreateProcess to start a secondary process (Child.exe) and waits for it to finish. Both exe files are embedding madExcept.
In some rare instances, this deadlocks and I have come up with the following instrumentation method inside Main.exe:
Create a watchdog thread
Get stack traces for all threads
Compare with previously saved stack traces, if equal, increase counter
If counter is above threshold, call NewException(etFrozen, nil, nil, False), dump the report and stop the application.
This works well in preventing the application to run "forever", but it only tells me that Main.exe is stuck waiting for Child.exe
To really figure out what's going on, I would need the same report dump for Child.exe and so was wondering if I could send a "signal" to that exe that madExcept would automatically intercept and thus create a bugreport file. Is there such a mechanism in place inside madExcept?
I know how to implement this, but if it's already there, it would be better to use it.
Getting a "frozen" bug report for a secondary exe file
Re: Getting a "frozen" bug report for a secondary exe file
It's kinda already there. See madTraceProcess. Source code should be included. It has some dependencies, though, but you can probably drop most of them. E.g. you can replace CreateRemoteThreadEx with CreateRemoteThread.
Re: Getting a "frozen" bug report for a secondary exe file
Thanks for the hint, I did not know this existed.
I managed to adapt it into a function that gets a Process Id and returns a string, it's all I needed and it works just fine. Do you want me to post it somewhere?
With that I can see what the child process is doing, which is looping on Application.Idle, which is weird, but there's nothing madExcept can do about that. Back to the drawing board, but at least now, I can inspect all the puzzle pieces.
I managed to adapt it into a function that gets a Process Id and returns a string, it's all I needed and it works just fine. Do you want me to post it somewhere?
With that I can see what the child process is doing, which is looping on Application.Idle, which is weird, but there's nothing madExcept can do about that. Back to the drawing board, but at least now, I can inspect all the puzzle pieces.
Re: Getting a "frozen" bug report for a secondary exe file
How long is that function? If it's not too long, I suppose you could paste it into a "code" block here, in case it might be helpful to other users.
Re: Getting a "frozen" bug report for a secondary exe file
I was waiting for your validation as this is based on your own code. So here it goes:
Code: Select all
function GetProcessBugReport(ProcessId: DWORD): string;
var
SecurityAttributes: TSecurityAttributes;
SecurityDescriptor: TSecurityDescriptor;
ProcessHandle: THandle;
TraceFunction: Pointer;
{$ifdef win64}
SessionId: DWORD;
{$endif}
I, J: Integer;
FileMappingHandle: THandle;
C: DWORD;
RemoteString: AnsiString;
Buffer: Pointer;
begin
SecurityAttributes.nLength := SizeOf(SecurityAttributes);
SecurityAttributes.lpSecurityDescriptor := @SecurityDescriptor;
SecurityAttributes.bInheritHandle := False;
InitializeSecurityDescriptor(@SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(@SecurityDescriptor, True, nil, False);
ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessId);
if ProcessHandle <> 0 then
begin
try
TraceFunction := nil;
{$ifdef win64}
FileMappingHandle := OpenFileMappingA(FILE_MAP_READ, False, PAnsiChar('madTraceProcess' + IntToHexEx(ProcessId)));
if (FileMappingHandle = 0) and (GetLastError <> 5) then
begin
ProcessIdToSessionId(ProcessId, SessionId);
FileMappingHandle := OpenFileMappingA(FILE_MAP_READ, False, PAnsiChar('Session\' + IntToStrEx(SessionId) + '\madTraceProcess' + IntToHexEx(ProcessId)));
end;
if FileMappingHandle <> 0 then
begin
Buffer := MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
if Buffer <> nil then
begin
TraceFunction := pointer(Buffer^);
UnmapViewOfFile(Buffer);
end;
CloseHandle(FileMappingHandle);
end;
{$else}
with Process(ProcessHandle).ExportList do
if ItemCount = 0 then
begin
Exit('Opening the process failed. Try running as admin.');
end
else
begin
for I := 0 to ItemCount - 1 do
if Items[I].Name = 'madTraceProcess' then
begin
TraceFunction := Items[I].Address;
break;
end;
end;
{$endif}
if TraceFunction <> nil then
begin
EmptyClipboard;
if GetVersion and $80000000 = 0 then
begin
FileMappingHandle := CreateFileMapping(INVALID_HANDLE_VALUE, @SecurityAttributes, PAGE_READWRITE, 0, $100000, 'Global\madTraceProcessMap');
if FileMappingHandle = 0 then
FileMappingHandle := CreateFileMapping(INVALID_HANDLE_VALUE, @SecurityAttributes, PAGE_READWRITE, 0, $100000, 'madTraceProcessMap');
end
else
begin
FileMappingHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, $100000, 'madTraceProcessMap');
end;
try
if FileMappingHandle <> 0 then
C := $100000
else
C := 0;
C := CreateRemoteThread(ProcessHandle, @SecurityAttributes, 0, TraceFunction, pointer(C), CREATE_SUSPENDED, C);
if C <> 0 then
begin
SetThreadPriority(C, THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(C);
WaitForSingleObject(C, INFINITE);
CloseHandle(C);
RemoteString := '';
if FileMappingHandle <> 0 then
begin
Buffer := MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
if Buffer <> nil then
begin
RemoteString := PAnsiChar(Buffer);
UnmapViewOfFile(Buffer);
end;
end;
if RemoteString = '' then
try
RemoteString := AnsiString(Clipboard.AsText);
except
end;
I := PosText(AnsiString('exception number'), RemoteString);
if I > 0 then
begin
J := PosText(#$D#$A, RemoteString, I);
if J > 0 then
Delete(RemoteString, I, J - I + 2);
end;
I := PosText(AnsiString('exception message'), RemoteString);
if I > 0 then
begin
J := PosText(#$D#$A, RemoteString, I);
if J > 0 then
Delete(RemoteString, I, J - I + 2);
end;
Exit(DecodeUtf8(RemoteString));
end
else
begin
C := GetLastError;
Exit(SysErrorMessage(C));
end;
finally
CloseHandle(FileMappingHandle);
end;
end;
finally
CloseHandle(ProcessHandle);
end;
end;
Result := Format('Process %d does not seem to embed madExcept.', [ProcessId]);
end;
Re: Getting a "frozen" bug report for a secondary exe file
Looks good, thanks.