CEF crashes when calling functions in a particular DLL - c++

I have an MSVC project, this project consists of multiple DLLs called from an executable. One of these DLLs initializes CEF (Chromium Embedded Framework) and another provides some other general functionality, We'll call them cefDLL and generalDLL. The calls go like this:
All the calls are done from the executable.
I call functions in the cefDLL to initialize CEF.
I call functions the second generalDLL.
Some thread internally in CEF crashes with a Windows error popup reporting "The application was unable to start correct (0xc0000124). Click OK to close the application.".
A Windows popup appears declaring Application.exe has stopped working.
The main thread continues running even if I close the program on the "has stopped working" popup.
If I try to run the debugger on the crashed program I get a blank Visual Studio, no call stack, no locals, nothing, not even the name of a failed DLL.
If I call a function from another DLL, a function from the executable itself or none at all, the code reaches my infinite loop just fine (I'm using an infinite loop to stop the rest of the program from running).
If I let it keep running into the rest of the program and don't stop it with an infinite loop two more threads in CEF crash for a total of three crashed threads. These produce exactly the same errors as the first thread. I'm not sure what causes this precisely as I haven't had the time to look into this yet.
Even if the functions called in generalDLL do absolutely nothing this still occurs. I am certain it is the act of calling them that causes this, if my code is
initializeCEF();
while (true)
{
}
it works, if the code is
initializeCEF();
someBlankFunctionInGeneralDLL();
while (true)
{
}
the thread crashes.
The initialization of CEF consists of this:
//Initialize
CefMainArgs mainArgs;
//Launch Threads
CefExecuteProcess(mainArgs, nullptr, nullptr);
//Settings
CefSettings settings;
settings.pack_loading_disabled = true;
settings.windowless_rendering_enabled = true;
settings.multi_threaded_message_loop = false;
settings.no_sandbox = true;
//Sandbox Info
void *sandboxInfo = nullptr;
//Launch System
CefInitialize(mainArgs, settings, nullptr, sandboxInfo);
Does anyone have the faintest idea what this could be caused by? It's easily among the strangest bugs I've ever encountered.
The project is giant at 50,000 lines or so and there aren't really any other relevant parts so I can't really provide any examples I'm afraid. Let me know if there's some code you think it would help to see though.

You know CEF is multi-process, right? Is it possible that your main application that is initializing CEF is not able to start multiple instances correctly, or is not passing the required command-line arguments to your CEF-containing DLL at startup? See this documentation about the structure of CEF applications: https://bitbucket.org/chromiumembedded/cef/wiki/Architecture#markdown-header-cef3
You can try starting CEF with the "--single-process" argument to force it to run single process (though shipping with this is very much not recommended because they don't test Chromium in this configuration - it is just for debugging). If you are not passing command line arguments to CEF that is probably the start of your problems. To do this, you can add a handler for OnBeforeCommandLineProcessing() in you CefApp derived class, as recommended by the creator of CEF here: http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=12928&p=25732&hilit=main_args#p25717 . The override would end up looking something like this:
void ServiceCenterApp::OnBeforeCommandLineProcessing(const CefString& process_type,
CefRefPtr<CefCommandLine> command_line) {
if(!command_line->HasSwitch("single-process")) {
command_line->AppendSwitch("single-process");
}
}
But I don't see you defining a CefApp derived class, that would be an argument to CefInitialize(). For example, the cefclient sample has this in their wWinMain():
// SimpleApp implements application-level callbacks. It will create the first
// browser instance in OnContextInitialized() after CEF has initialized.
CefRefPtr<SimpleApp> app(new SimpleApp);
followed by
// Initialize CEF.
CefInitialize(main_args, settings, app.get(), sandbox_info);
Where you tell CEF to use the derived App, where you would override whatever handlers you need to. You might want to start with the simple_app sample for a very basic override.
For the debugging issue, try attaching to all processes launched, assuming I'm incorrect and the multiple processes are launching correctly.

Related

Understanding and managing c++ program crash handling in windows

I have a c++ program compiled with MinGW which links to libmicrohttpd to run a webserver. It normally functions correctly, but I am trying to do some robustness testing and for my current test I have tried to disable the network interface. This results in the program crashing with the dialog box: "MyProgram.exe has stopped working - A problem caused the program to stop working correctly. Windows will close the program and notify you if a solution is available."
Rather than debug the program and potentially its dependencies, for my purposes, it would be fine if it would just crash silently without making the dialog box (I have another component that is meant to restart it). Is this possible to do via some sort of manifest or Windows API call?
It turns out there is a Windows API function called SetErrorMode. Passing the parameter SEM_NOGPFAULTERRORBOX will prevent the error dialog from being displayed on a crash.
There is also the RegisterApplicationRestart function which can be used to have Windows restart an application in the event of a crash (or other configurable reasons).

Visual Studio C++ Console Application Won't Run

What can be done when a C++ console application builds and launches but won't run any code, at least not any that the debugger can see? I have a program with a main function:
int main (int argc, char *argv[])
{
short retval = 0;
retval = samain ( (short) argc, argv);
return ((int) retval);
}
I put a breakpoint on the first line (retval=0) and the line after it just to be safe, and run. It shows a console window and hangs until I stop the debugger. The debug output shows a number of DLLs being loaded but nothing else. It ends with this line that looks very similar to the dozens before it:
'fcmtsysmd.exe' (Win32): Loaded 'C:\Windows\SysWOW64\RpcRtRemote.dll'. Cannot find or open the PDB file.
This is a program I know runs and functions in a "normal" environment because hundreds of people are using it and I haven't changed the code. The things different in my environment (because I'm in the process of rewriting our installation process) are:
I might not have all the dependencies installed properly.
One of the DLL dependencies that was causing an error earlier has been replaced by a newly built version with an Isolated COM reference instead of its usual COM reference because the COM object it was trying to access is not registered. (I'm trying to implement isolated COM in our new installation.)
So my question is, if an error is occurring before the first line of code executed, how can I track down the source of the problem?
I can't get a sensible call stack because even if I single step (F10 key) to start the program, it's hung right away. If I break at that point, I see the following call stack:
ntdll.dll!7743fdd1() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!7743fdd1() Unknown
ntdll.dll!77475f86() Unknown
ntdll.dll!77459809() Unknown
When I remove the isolated COM settings from the dependent DLL, I can get a access violation exception and stop on some code in the debugger. It's stopped on a function being called during the initialization of a static variable in another DLL. The strange thing is, when I add the isolated COM settings to the first DLL, and put a breakpoint on the other DLL, the breakpoint doesn't even get hit.
It turns out that the application was hanging during a call to CoCreateInstance triggered by some static initialization logic in one of the dependent DLLs. I guess the trick is trying to identify static initialization logic in dependent DLLs and putting breakpoints there. Unfortunately there doesn't appear to be any debug output to help identify which DLL's static initialization is executing when, so it's impossible to tell which DLL is the problem.
I will ask about how to identify the source of a hanging CoCreateInstance call in a separate question if there isn't already a question covering it: Application hung during CoCreateInstance when using Isolated COM
The final answer ended up being at https://stackoverflow.com/a/34076433/78162 (which I had to create myself).

VC6 to VS2013 MFC Runtime Error

I am trying to upgrade a legacy product from VC6 to VS2013 using toolset 12_xp. I can get the project to compile just fine however I am getting a runtime ASSERT and it seems related to CSingleLock lock() call.
CSingleLock slock(&CV7CmnSS::m_cs); // Wait for access
slock.Lock(m_dwTimeout); // <- this is the line that does it.
CV7CmnSS::m_cs is declared as a static object in a different class in another dll refrenced by this project.
the exe's header file has this CCriticalSection CV7CmnSS::m_cs;
as declared in CV7CmnSS header file static CCriticalSection m_cs;
I try to step through the MFC code (I know, i know...)
this is about all the further I can get...
mfc120d.dll!CCriticalSection::Lock(unsigned long dwTimeout) Line 118 C++ //<-- from the call stack window
_AFXMT_INLINE BOOL (::CCriticalSection::Lock(DWORD dwTimeout))
{
ASSERT(dwTimeout == INFINITE);
(void)dwTimeout;
return Lock();
}
the assert I box i get:
fairly generic..
Both the dll project are targeting the same toolset, 12_xp, both use MBCS, both are using MFC as a shared dll. Both are using Multithreaded debug dll setting.
I suspect a cross threading issue? But I am not sure how to proceed.
If there is anymore info I can provide please let me know.
EDIT:
I forgot to add this little gem, if I run the program in release without debugging I am able to get a little further with the app, however this strange message pops up....
The code you showed reveals the problem: there's an assert that requires the dwTimeout parameter to be INFINITE. As you can see from the code, and as mentioned in the CCriticalSection::Lock documentation, that parameter is ignored, so you can just change the code to pass INFINITE as the parameter, or just call the overload that takes no parameters (which does the same thing).
As for why the error doesn't happen in release mode, it's because asserts are only compiled in debug mode, so the assert never happens. Whatever is causing that message box is completely unrelated to the assert.

Heisenbug issue with using a dll. What do I do next?

I am working on a system that uses a Voltage Controlled Oscillator chip (VCO) to help process a signal. The makers of the chip (Analog Devices) provide a program to load setup files onto the VCO but I want to be able to setup the chip from within the overarching signal processing control system. Fortunately Analog Devices also provides a DLL to interface with their chip and load setup files myself. I am programming in Visual C++ 6.0 (old I know) and my program is a dialog application.
I got the system to work perfectly writing setup files to the card and reading its status. I then decided that I needed to handle the case where there are multiple cards attached and one must be selected. The DLL provides GetDeviceCount() which returns an integer. For some reason every time the executable runs it returns 15663105 (garbage I assume). Whenever I debug my code however the function returns the correct number of cards. Here is my call to GetDeviceCount().
typedef int (__stdcall *GetDeviceCount)();
int AD9516_Setup()
{
int NumDevices;
GetDeviceCount _GetDeviceCount;
HINSTANCE hInstLibrary = LoadLibrary("AD9516Interface.dll");
_GetDeviceCount = (GetDeviceCount)GetProcAddress(hInstLibrary,"GetDeviceCount");
NumDevices = _GetDeviceCount();
return NumDevices;
}
Just to be clear: every other function from the DLL I have used is called exactly like this and works perfectly in the executable and debugger. I did some research and found out that a common cause of Heisenbugs is threading. I know that there is some threading behind the scenes in the dialogs I am using so I deleted all my calls to the function except one. I also discovered that the debugger code executes slower than executable code and I thought the chip may not have enough time to finish processing each command. First I tried taking up time between each chip function call by inserting an empty for loop and when that did not work I commented out all other calls to the DLL.
I do not have access to the source code used to build the DLL and I have no idea why its function would be returning garbage in the executable and not debugger. What other differences are there between running in debugger and executing that could cause an error? What are some other things I can do to search for this error?
Some compilers/IDEs add extra padding to variables in debug builds or initialize them to 0 - this might explain the differences you're encountering between debugging and "normal" execution.
Some things that might be worth checking:
- are you using the correct calling convention?
- do you get the same return value if no devices are connected?
- are you using the correct return type (uint vs int vs long vs ..)?
Try setting _GetDeviceCount to 0 before calling the function; that could be what the debugger is doing for you.

Program Doesn't Terminate Correctly

I'm writing a computer vision app (C++ and OpenCV). I am creating a GUI for it with wxWidgets - this is very simple; a button-press event calls the tracker app to begin.
My call to terminate the app (i.e. on clicking to close button) is as follows:
// Exiting the App
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
This usually works with more trivial GUI apps. However, on this occasion, the frame disappears yet, in the task manager, the process seems to continue running and holding memory. It's very annoying because if I run or debug the application and later make some changes and try to run again, without manually terminating the process beforehand, the compiler throws a link error because the .exe is
not found or not built by the last incremental link.
Tried inserting a brute force exit(1); in the onQuit method but it causes the app to crash.
I'm not sure what it is.. when running without the GUI, the app runs and terminates fine (albeit it is called slightly differently - from the main() function instead of from a button-press event handler which calls an abstract base class).
Is it possible that it is because a class is being declared with global scope? As in, in one file I have an instance of a class declared outside of any class method? Perhaps wxWidgets can't handle this?
To clarify:
The frame I'm closing is a top level frame. I had no problems with the exact same GUI code when it does not call the computer vision methods.
I haven't specifically coded any multi-threading but to begin with, I was getting an error that said "Error: Cannot initialize OLE". To fix this, I had to set wxUSE_DRAG_AND_DROP, wxUSE_CLIPBOARD, wxUSE_OLE and wxUSE_OLE_AUTOMATION to 0 (instead of 1) and then (re)compile wxWidgets.
Just wondering, is there some kind of threading going on with HighGUI that is inconsistent with WxWidgets? Has anybody else encountered similar problems?
::wxExit
void wxExit()
Exits application after calling wxApp::OnExit. Should only be used in an emergency: normally the top-level frame should be deleted (after deleting all other frames) to terminate the application. See wxCloseEvent and wxApp.
Include files
<wx/app.h>
You can also simply call the crt function exit() which will instantly shut down everything.
However, if you want to more polite than these rather brutal methods ( which you may want to do in particular if you have placed some special shut down code in wxApp::OnExit
) then you want to find the top level window and close that. To do this from anywhere in your code
wxGetApp().GetTopWindow()->Close()
Thanks for all the help, I have solved the problem. Seems fairly obvious now but couldn't figure it out at the time!
Originally, my computer vision app was called from a main function. However, with the new GUI code there is no need for a main so I replaced the original main with a shell class.
Though I had been careful to free allocated memory within the methods of my computer vision classes I had not been so careful with the original main function because once that function ended, all memory previously in use would be cleared up by the program's regular exiting.
The difference with the new GUI code is that when the shell class is finished - the program is still running. The clue was in the fact that even when the computer vision app had ended, the blue light on my webcam was still shining.
* Be sure to call cvReleaseCapture( &capture ); to free up that thread and release the hardware *
Your call to Close only closes the frame, but doesn't stop the application, because it is not the last top level window. The wxWidget contains a topic Window Deletion Overview. It states that
A wxWidgets application automatically exits when the last top level window (wxFrame or wxDialog), is destroyed. Put any application-wide cleanup code in wxApp::OnExit (this is a virtual function, not an event handler).
Is your frame the top-level frame? If not, you may have to call Close or Destroy on a top-level frame.