CefSharp/Cef libcef.dll stack overflow (0xC00000FD) - c#

CefSharp Winforms Version 43.0.0.0, libcef.dll 3.2357.1287.
When selecting text in a text box, and then hitting a key on the on screen keyboard (does not happen on the normal keyboard), I sometimes get a stack overflow in libcef.dll.
I am ripping my hair out trying to isolate the cause. One thing that is slowing me down is the inability to connect a proper pdb file to the dll. Despite downloading all variations of it from CefBuilds.
I have various crash dumps, and was wondering if anybody else has had experience troubleshooting this kind of thing. WinDBG may as well be chinese, with DebugDiag being much easier to follow, but without the valid pdb file neither are any use at all.
I cannot recreate the issue in the winform example application, so its definitely local to us, so I am currently ripping code out left right and center to isolate the cause, but would really appreciate some guidance on how to load the pdb file into debugdiag to stop this:
Despite this:
libcef.dll version:
For anyone interested, this is the current crashing thread's stack trace:
... and on and on and on...
I guess the main question is does anybody know what could be causing the stack overflow? (This problem existed in 41.0.0 in the winform example application, now it only exists within our own application in 43.0.0).
With a secondary question of why aren't the pdb files loading in debugdiag.
Edit. I am compiling in 32bit, and it appears there is no pdb file for the 32 bit edition of libcef.dll v3.2357.1287. In fact, according to cefbuilds.com this file does not exist.

It appeared that although I couldn't re-create the issue using the winform example's main form, I could whilst using its SimpleBrowserForm.cs.
This allowed me to compare the different implementations.
In the main form, once the browser control is initialised, a hacky message loop interceptor is created, to pass internal WM_MOUSEACTIVATE events up to the parent container. This appears to be an effort to ensure that if a context menu is open at the time the click is received, it will be closed by the click event (chromium suppresses internal mouse clicks it seems).
private void OnIsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs args)
{
if (args.IsBrowserInitialized)
{
ChromeWidgetMessageInterceptor.SetupLoop((ChromiumWebBrowser)Browser, (message) =>
{
const int WM_MOUSEACTIVATE = 0x0021;
const int WM_NCLBUTTONDOWN = 0x00A1;
if (message.Msg == WM_MOUSEACTIVATE) {
// The default processing of WM_MOUSEACTIVATE results in MA_NOACTIVATE,
// and the subsequent mouse click is eaten by Chrome.
// This means any .NET ToolStrip or ContextMenuStrip does not get closed.
// By posting a WM_NCLBUTTONDOWN message to a harmless co-ordinate of the
// top-level window, we rely on the ToolStripManager's message handling
// to close any open dropdowns:
// http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/ToolStripManager.cs,1249
var topLevelWindowHandle = message.WParam;
PostMessage(topLevelWindowHandle, WM_NCLBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
}
});
}
}
Anyway, with this weird little hack in place, my stack overflow crash goes away.
I have raised a github ticket to try get the underlying issue resolved, but for now this is preventing the issue.

Related

VS 17 breaking on all exceptions

Visual Studio 2017 is (kind of suddenly) breaking on all exceptions. That means, if I deactivate them in the exceptions settings (pressing CTRL + ALT + E while debugging), the debugger still breaks on them. I don't know wether this is just a bug of VS I can't change and therefore have to live with, or wether there is a simple solution for it.
This is the exception settings window:
and this the exception VS breaks on:
By the way, I also tried that beautiful minus (nothing happens if I press it) or adding a impossible condition (VS still broke on the exception).
I also tested other exceptions (by simply throwing them), which I deactivated before, and they get thrown as well and I tested the same issue in other projects, where it appeared as well:
I actually even put the whole stuff into a try catch statement but VS still breaks:
InitializeComponent ();
try
{
var t = new Thread (() =>
{
while (!IsHandleCreated) {} //It breaks here (similiar to the screenshots)
while (true)
Invoke (new Action (() => Size = new Size ()));
});
while (true)
{
t.Start ();
Thread.Sleep (100);
t.Abort ();
}
}
catch (ThreadAbortException) { }
It doesn't appear in other IDEs (like Rider) on my PC and doesn't occurr on other PCs in VS. It didn't always occurr on my PC, it just started recently and only in debugging mode. And if I continue the execution (with F5) it just continues normally.
EDIT As I put the try catch inside the thread it behaved a little bit different (I'm sorry for putting pictures in here, but I think they're more expressive in that case):
Can anybody explain this behaviour?
EDIT It seems to be normal for ThreadAbortExceptions to break again at the end of a catch statement. However, VS still shouldn't break on this exception at all.
I was having a similar problem.
I fixed it by unchecking "Break when exceptions cross AppDomain or managed/native boundaries" in Tools > Options > Debugging > General
I fixed it by unchecking Enable Just My Code in Tools > Options > Debugging > General
I can't confirm whether this happens with other project types, but it happens to me consistently with (Visual Studio Tools for Python) VSTP.
Although it is less than satisfactory, it can at least silence the exceptions and allow you to continue working in peace until a better solution surfaces. In my case, it was nearly impossible to debug my code, since StopIteration breaks during every iteration.
Select Debug > Windows > Exception Settings or press Ctrl-Alt-E. Y
Right click anywhere on the Window and select Show Columns > Additional Actions. You will have an "Additional Actions" column appear if it doesn't already.
Right click on a specific exception you want to silence or click the top level checkbox to select an entire category of exceptions, i.e. Python Exceptions. Click Continue When Unhandled in User Code.
Repeat for each additional exception or category of exceptions.
I know it's a little late for this, but ThreadAbortException is different from all other exceptions, and requires some special handling, otherwise it is automatically re-thrown at the end of all catch blocks if you don't actually handle it the way it's supposed to be handled.

LINQPad: Assert() prints "Fail:" and continues instead of breaking

In LINQPad, Debug.Assert() and Trace.Assert() from the System.Diagnostics namespace don't work as expected.
Instead of breaking - i.e. popping up a message box or whatever else happens to be configured for <trace> - they simply print "Fail:" or "Fehler:" to the output window and let the program continue on its merry way. In other words, instead of a noisy, unignorable explosion there are only near invisible micro-farts that intersperse "Fail:" into the textual output.
Is there any way of getting Assert() to revert to the default behaviour under LINQPad?
Alternatively, is there a simple way of mocking a Trace.Assert() so that failure results in a noisy explosion (i.e. exception, message box, whatever) and the source of the failure is pinpointed in the form of a line number or similar?
My unit tests are based on Trace.Assert(), which makes them totally useless if the function cannot break the program at the point of failure.
In Visual Studio everything works normally but not in LINQPad. I haven't fiddled with any system-wide settings but I did install Mono at some point in time. I went through all settings in LINQPad with a fine comb but to no avail. The LINQPad version is 4.57.02 (non-free), running on Windows 7 Pro (German) and Windows 8.1 Pro (English).
I googled high and wide but the only thing I could find is the topic Trace.Assert not breaking, neither showing the message box here on Stack Overflow. Its title certainly looks promising but the answers therein don't.
P.S.: I tried mocking by adding
class Trace
{
public static void Assert (bool condition)
{
if (!condition)
throw new Exception("FAIL!");
}
}
to the LINQ script and setting a breakpoint on the throw statement. Clicking on the relevant call stack entry in LINQPad's debugger takes me to the relevant source line, so this sort of works. However, I couldn't find an equivalent to FoxPro's SET DEBUG ON for invoking the debugger directly from the source code instead of having to set a breakpoint on the throw...
To answer the second half of your question, i.e., how do you get the LINQPad debugger to break when an exception is thrown, the answer is to click either of the 'Bug' icons on the toolbar.
Click Break when exception is unhandled (red bug) to make your query break whenever an unhandled exception is thrown.
Click Break when exception is thrown (blue bug) to make your query break whenever an exception is thrown, whether or not it is handled.
You can get LINQPad to make either setting the default by right-clicking and choosing Set as default. (Doing so forces the debugger to always attach to your queries, which incurs a small performance cost.)
As to why Debug.Assert(false) doesn't display a dialog, this is because this behavior hasn't been implemented in LINQPad. You could implement this easily as an extension, by adding the following code to My Extensions:
public class NoisyTracer : TextWriterTraceListener
{
public static void Install()
{
Trace.Listeners.Clear();
Trace.Listeners.Add (new NoisyTracer (Console.Out));
}
public NoisyTracer (TextWriter writer) : base (writer) { }
public override void Fail (string message, string detailMessage)
{
base.Fail (message, detailMessage);
throw new Exception ("Trace failure: " + message);
}
}
Then, to enable, write your query as follows:
NoisyTracer.Install();
Debug.Assert (false);

How to catch a external exception

I'm using the nVLC dll's for using the VLC Media Player within my application. It works like a charm except for one thing. I have a DataGridView with a list of movies. When I select a movie from that DataGridView it starts playing the movie within the panel that is handled by nVLC. I also use filters to filter the movies within the DataGridView. When I do this a couple of times I get an error from the nVLC DLL:
CallbackOnCollectedDelegate occurred
Managed Debugging Assistant 'CallbackOnCollectedDelegate' has detected a problem in 'C:\Users\User\Documents\Visual Studio 2013\Projects\Soft.UltimateMovieManager\Soft.UltimateMovieManager\bin\Release\Soft.UltimateMovieManager.vshost.exe'.
Additional information: A callback was made on a garbage collected
delegate of type
'nVLC.Implementation!Implementation.VlcEventHandlerDelegate::Invoke'.
This may cause application crashes, corruption and data loss. When
passing delegates to unmanaged code, they must be kept alive by the
managed application until it is guaranteed that they will never be
called.
The problem is that I can't catch that exeption. Even when I set a try/catch on the application itself, it still can't be handled.
Is this something I can resolve myself or is this a problem of the nVLC dll I use?
if (!string.IsNullOrEmpty(video_url))
{
if (pnlStartVideo != null)
{
pnlStartVideo.Dispose();
}
pnlStartVideo = new System.Windows.Forms.Panel();
pnlStartVideo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
pnlStartVideo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
pnlStartVideo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
pnlStartVideo.Location = new System.Drawing.Point(pnlStartInfo.Location.X, (pnlStartInfo.Location.Y + (pnlStartInfo.Height - 1)));
pnlStartVideo.Name = "pnlStartVideo";
pnlStartVideo.Size = new System.Drawing.Size(275, 153);
pnlStartVideo.TabIndex = 3;
tpStart.Controls.Add(pnlStartVideo);
m_factory = new MediaPlayerFactory(true);
m_player = m_factory.CreatePlayer<IDiskPlayer>();
m_player.WindowHandle = pnlStartVideo.Handle;
m_player.Events.PlayerStopped += Events_PlayerStopped;
UISync ui = new UISync();
ui.Init(this);
m_media = m_factory.CreateMedia<IMedia>(video_url);
m_player.Open(m_media);
m_media.Parse(true);
m_media.Events.StateChanged += Events_StateChanged;
m_player.Play();
}
Managed Debugging Assistant 'CallbackOnCollectedDelegate' ...
It is not a catchable exception since it is not an exception at all. A managed debugging assistant is helper code added to the debugger that can detect various mishaps at runtime. This one steps in when it sees the VLC player trying to use a disposed delegate object. Without the debugger your program will keel over and die in a much worse way, an AccessViolationException, not catchable either since it is native code that fails.
Looking at the VLC wrapper source code, you must create the m_player instance only once to avoid this failure mode. When you create it over and over again like you do now, the previous IDiskPlayer instances are not reference anywhere anymore. The garbage collector will collect them, big kaboom when the native VLC code makes the callback to fire an event. The wrapper also doesn't implement proper cleanup that I can see, ensuring that the native code cannot fire events anymore when the object is disposed.
Making the m_player variable static is strongly recommended. Assign it just once.
Fixing the wrapper would require writing the equivalent of initializeEventsEngine() but setting all the callbacks back to null. This is not necessarily straight-forward, there are probably threading races involved. Taking a dependency on this code is a liability, you might want to keep shopping.

Messagebox in Catch block not always showing [duplicate]

When I create a new project, I get a strange behavior for unhandled exceptions. This is how I can reproduce the problem:
1) create a new Windows Forms Application (C#, .NET Framework 4, VS2010)
2) add the following code to the Form1_Load handler:
int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;
I would expect that VS breaks and shows an unhandled exception message at the second line. However, what happens is that the third line is just skipped without any message and the application keeps running.
I don't have this problem with my existing C# projects. So I guess that my new projects are created with some strange default settings.
Does anyone have an idea what's wrong with my project???
I tried checking the boxes in Debug->Exceptions. But then executions breaks even if I handle the exception in a try-catch block; which is also not what I want. If I remember correctly, there was a column called "unhandled exceptions" or something like this in this dialog box, which would do excatly what I want. But in my projects there is only one column ("Thrown").
This is a nasty problem induced by the wow64 emulation layer that allows 32-bit code to run on the 64-bit version of Windows 7. It swallows exceptions in the code that runs in response to a notification generated by the 64-bit window manager, like the Load event. Preventing the debugger from seeing it and stepping in. This problem is hard to fix, the Windows and DevDiv groups at Microsoft are pointing fingers back and forth. DevDiv can't do anything about it, Windows thinks it is the correct and documented behavior, mysterious as that sounds.
It is certainly documented but just about nobody understands the consequences or thinks it is reasonable behavior. Especially not when the window procedure is hidden from view of course, like it is in any project that uses wrapper classes to hide the window plumbing. Like any Winforms, WPF or MFC app. Underlying issue is Microsoft could not figure out how to flow exceptions from 32-bit code back to the 64-bit code that triggered the notification back to 32-bit code that tries to handle or debug the exception.
It is only a problem with a debugger attached, your code will bomb as usual without one.
Project > Properties > Build tab > Platform target = AnyCPU and untick Prefer 32-bit. Your app will now run as a 64-bit process, eliminating the wow64 failure mode. Some consequences, it disables Edit + Continue for VS versions prior to VS2013 and might not always be possible when you have a dependency on 32-bit code.
Other possible workarounds:
Debug > Exceptions > tick the Thrown box for CLR exceptions to force the debugger to stop at the line of code that throws the exception.
Write try/catch in the Load event handler and failfast in the catch block.
Use Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) in the Main() method so that the exception trap in the message loop isn't disabled in debug mode. This however makes all unhandled exceptions hard to debug, the ThreadException event is pretty useless.
Consider if your code really belongs in the Load event handler. It is very rare to need it, it is however very popular in VB.NET and a swan song because it is the default event and a double-click trivially adds the event handler. You only ever really need Load when you are interested in the actual window size after user preferences and autoscaling is applied. Everything else belongs in the constructor.
Update to Windows 8 or later, they have this wow64 problem solved.
In my experience, I only see this issue when I'm running with a debugger attached. The application behaves the same when run standalone: the exception is not swallowed.
With the introduction of KB976038, you can make this work as you'd expect again. I never installed the hotfix, so I'm assuming it came as part of Win7 SP1.
This was mentioned in this post:
The case of the disappearing OnLoad exception – user-mode callback exceptions in x64
Here's some code that will enable the hotfix:
public static class Kernel32
{
public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1;
[DllImport("Kernel32.dll")]
public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags);
[DllImport("Kernel32.dll")]
public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags);
public static void DisableUMCallbackFilter() {
uint flags;
GetProcessUserModeExceptionPolicy(out flags);
flags &= ~PROCESS_CALLBACK_FILTER_ENABLED;
SetProcessUserModeExceptionPolicy(flags);
}
}
Call it at the beginning of your application:
[STAThread]
static void Main()
{
Kernel32.DisableUMCallbackFilter();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
I've confirmed (with the the simple example shown below) that this works, just as you'd expect.
protected override void OnLoad(EventArgs e) {
throw new Exception("BOOM"); // This will now get caught.
}
So, what I don't understand, is why it was previously impossible for the debugger to handle crossing kernel-mode stack frames, but with this hotfix, they somehow figured it out.
As Hans mentions, compile the application and run the exe without a debugger attached.
For me the problem was changing a Class property name that a BindingSource control was bound to. Running without the IDE I was able to see the error:
Cannot bind to the property or column SendWithoutProofReading on the
DataSource. Parameter name: dataMember
Fixing the BindingSource control to bind to the updated property name resolved the problem:
I'm using WPF and ran into this same problem. I had tried Hans 1-3 suggestions already, but didn't like them because studio wouldn't stop at where the error was (so I couldn't view my variables and see what was the problem).
So I tried Hans' 4th suggestion. I was suprised at how much of my code could be moved to the MainWindow constructor without any issue. Not sure why I got in the habit of putting so much logic in the Load event, but apparently much of it can be done in the ctor.
However, this had the same problem as 1-3. Errors that occur during the ctor for WPF get wrapped into a generic Xaml exception. (an inner exception has the real error, but again I wanted studio to just break at the actual trouble spot).
What ended up working for me was to create a thread, sleep 50ms, dispatch back to main thread and do what I need...
void Window_Loaded(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Thread.Sleep(50);
CrossThread(() => { OnWindowLoaded(); });
}).Start();
}
void CrossThread(Action a)
{
this.Dispatcher.BeginInvoke(a);
}
void OnWindowLoaded()
{
...do my thing...
This way studio would break right where an uncaught exception occurs.
A simple work-around could be if you can move your init code to another event like as Form_Shown which called later than Form_Load, and use a flag to run startup code at first form shown:
bool firstLoad = true; //flag to detect first form_shown
private void Form1_Load(object sender, EventArgs e)
{
//firstLoad = true;
//dowork(); //not execute initialization code here (postpone it to form_shown)
}
private void Form1_Shown(object sender, EventArgs e)
{
if (firstLoad) //simulate Form-Load
{
firstLoad = false;
dowork();
}
}
void dowork()
{
var f = File.OpenRead(#"D:\NoSuchFile756.123"); //this cause an exception!
}

Check if a dll is installed and available

I am trying to make an application that may rely on a Wacom tablet. It is not necessary for the program to work, but it is a nice addition. Although, it should also work on computers without the Wintab32.dll installed and I would like to make a check to see if the DLL is available.
This piece of code generates an error and I would like to catch the error before it is generated. I am using WintabDN to support .net Wacom applications.
if (WintabDN.CWintabInfo.IsWintabAvailable())
{
// Initialize Wintab
WintabLib.Initialize(true);
WintabLib.OnWintabPacketReceived += WintabLib_OnWintabPacketReceived;
}
FAILED IsWintabAvailable: System.DllNotFoundException: Unable to load
DLL 'Wintab32.dll': The specified module could not be found.
(Exception from HRESULT: 0x8007007E)
at WintabDN.CWintabFuncs.WTInfoA(UInt32 wCategory_I, UInt32 nIndex_I, IntPtr IpOutput_O)
at WintabDN.CWintabInfo.IsWintabAvailable()
The problem with this error is that it is a messagebox and not an exception thrown by the package. How can I prevent this messagebox from showing up?
It's a bit tricky, because the underlying exception is already being handled.
Trying to block the messagebox from showing is going to be difficult, if not impossible. You can do something really hacky like a watcher thread to catch the foreground window changing, then manually sending a mouse click message to the application's underlying message queue to try and trigger the OK button on the message box.
So I have two suggestions: this is the official topic on DLL search order; you can use it to emulate the search and find the file in advance.
If you don't want to do that you could import the LoadLibrary method from kernel32.dll and then call that to try and load the DLL that the WintabDN library is trying to use; if you get an exception then you know that the WintabDN library will also. Here's an almost related topic that'll help bind LoadLibrary: http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_.aspx
Try following which answers:
(The Wintab SDK examples won't run without Wintab installed on the system. How can I make my program work if there is no tablet (no Wintab) on the system?)
http://www.wacomeng.com/windows/docs/WacomWindevFAQ.html
How can I prevent this messagebox from showing up?
You can't:
public static bool IsWintabAvailable()
{
IntPtr buf = IntPtr.Zero;
bool status = false;
try
{
status = (CWintabFuncs.WTInfoA(0, 0, buf) > 0);
}
catch (Exception ex)
{
MessageBox.Show("FAILED IsWintabAvailable: " + ex.ToString());
}
return status;
}
:D
I hate library developers, writing such kind of code. They shouldn't decide, what error-handling mechanism you will choose.
But it is open-source, you can fix this issue.
Or you can post a bug at their tracker and wait, when they will fix it.

Categories