Calling an unmanaged delegate with BeginInvoke - c#

I've a delegate to an unmanaged function on a DLL (which I loaded using GetProcAddress). I can call this delegate with no trouble. When I call the delegates with BeginInvoke, however, I get the following exception:
Managed Debugging Assistant 'FatalExecutionEngineError' has detected a problem in '...'.
Additional Information: The runtime has encountered a fatal error. The address of the
error was at 0x63fd8687, on thread 0xb4c. The error code is 0xc0000005. This error may
be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common
sources of this bug include user marshaling errors for COM-interop or PInvoke, which
may corrupt the stack.
This is the code:
private void OnConnectFinished(IAsyncResult a_oResult)
{
ConnectDelegate l_oDelegate = (ConnectDelegate)a_oResult.AsyncState;
if (ConnectFinished != null)
{
ConnectFinished(l_oDelegate.EndInvoke(a_oResult));
}
}
public bool Connect()
{
AsyncCallback l_oCallback = new AsyncCallback(OnConnectFinished);
IAsyncResult l_oResult = DLLConnect.BeginInvoke(l_oCallback, DLLConnect);
//This Works!:
//bool l_bResult = DLLConnect(m_oConnectFinishedDelegate);
//return l_bResult;
return true;
}
Any ideas on why is this happening?

Passing the delegate as userState (the second argument in BeginInvoke) seems suspicious. Will it work if you pass null there? (Yes, I know that your callback won't work, but this issue can be handled another way. Let's check if the reported error disappears.)

Related

Exception on exit() when using C# event source with c++ sink

I have a COM object, implemented in a C# .dll, named ComClass which sources events. Then, I have a C++ object, SimpleSink, that sinks the events sent from ComClass. The event source/sink mechanism works great. But, when the CRT calls exit(), I'm getting a memory access exception thrown from the following code in exe_common.inl
//
// main has returned; exit somehow...
//
if (!__scrt_is_managed_app())
exit(main_result); // Exception is thrown.
The text of the exception message is as follows.
Exception thrown at 0x00000004 in Cpp.exe: 0xC0000005: Access violation executing location 0x00000004.
I understand that something is attempting to access a junk memory location, but I'm unsure as to what. I researched the issue and I came across this, from Microsoft.
https://msdn.microsoft.com/en-us/library/ms235234.aspx
Once the common language runtime (CLR) enters shutdown mode, native functions have limited access to CLR services. When attempting to call Release on a COM object compiled with /clr, the CLR transitions to native code and then transitions back into managed code to service the IUnknown::Release call (which is defined in managed code). The CLR prevents the call back into managed code since it is in shutdown mode.
I'm not sure if this is applicable only to C++ /clr compiled COM objects, or all CLR compiled COM objects. It may be a cold lead, so to speak. I understand that I could disable the exception and 'probably' go about my business, but that makes me feel oily. So, the question is, how can I prevent this exception when my program shuts down?
Here it is.
int main()
{
CoInitialize(NULL);
// explicit scope so that the smart pointer destructs at the correct time
{
IComClassPtr source;
HRESULT createInstance = source.CreateInstance(__uuidof(ComClass));
SinkSimple sink;
HRESULT advise = sink.DispEventAdvise(source);
try
{
source->FireEvent();
}
catch (const _com_error& ex)
{
std::cout << "Error: " << ex.Description();
}
HRESULT unadvise = sink.DispEventUnadvise(source);
}
CoUninitialize();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return 0;
}

Calling a managed function (C#) via Marshal.GetFunctionPointerForDelegate from a native (C++) thread

I'm using Marshal.GetFunctionPointerForDelegate to get a function pointer to a native function. I then pass this function pointer to some unmanaged code via the regular DllImport mechanism. I'm using this for callbacks; the native code calls back into the managed (C#) code. Everything works fine as long as the callback happens on the same thread. If I attempt to call the managed function from a thread I created via CreateThread it fails.
Is it possible to call back into managed code from a native thread simply via the function pointer that GetFunctionPointerForDelegate returns?
C#:
//in class definition
[DllImport("SomeDll")]
public static extern void SetCallback(System.IntPtr function);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public void delegate SomeDelgateType();
public SomeDelgateType OnCallback;
//a function to implement the callback
public void Callback()
{
}
//inside a setup function
OnCallback = new SomeDelgateType(Callback);
SetCallback(Marshal.GetFunctionPointerForDelegate(OnCallback);
The problem occurs when I call the function pointer from C++. If it's on the original thread that made the SetCallback function everything works. If I create a native thread with CreateThread and then try to call the function via the pointer, I get the following exception:
Unhandled exception at 0x76674598 (KernelBase.dll) in MissionControl.exe: 0xE0434352 (parameters: 0x80070057, 0x00000000, 0x00000000, 0x00000000, 0x73DB0000).
With the following stack trace:
KernelBase.dll!_RaiseException#16() Unknown
clr.dll!RaiseTheExceptionInternalOnly(class Object *,int,int) Unknown
clr.dll!IL_Throw(class Object *) Unknown
02bbc34b() Unknown
[Frames below may be incorrect and/or missing]
[External Code]
native_function_on_different_thread();
Turns out that you can actually call from an unmanaged thread. The catch is that if you're debugging your managed application, no break points inside the callback will actually ht in the debugger, but your code will still be executed. To get your breakpoints to work, you'll need to enable "native code debugging" (even though your breakpoint is in managed code!) by going to Project -> Properties -> Debug -> Enable native code debugging.

Implications of throwing exception in delegate of unmanaged callback

What are the implications or unperceived consequences of throwing an exception inside of a delegate that is used during an unmanaged callback? Here is my situation:
Unmanaged C:
int return_callback_val(int (*callback)(void))
{
return callback();
}
Managed C#:
[DllImport("MyDll.dll")]
static extern int return_callback_val(IntPtr callback);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int CallbackDelegate();
int Callback()
{
throw new Exception();
}
void Main()
{
CallbackDelegate delegate = new CallbackDelegate(Callback);
IntPtr callback = Marshal.GetFunctionPointerForDelegate(delegate);
int returnedVal = return_callback_val(callback);
}
The native code will bomb on the unhandled exception and the program terminates.
If you actually want to handle that exception then you need to use the custom __try/__catch keywords in the native code. Which is pretty useless, all the details of the managed exception are lost. The only distinguishing characteristic is the exception code, 0xe0434f4d. Since you cannot know exactly what went wrong, you cannot reliably restore the program state either. Better not catch it. Or better not throw it.
I think the correct way to say to a COM Object you have an exception is simply to return HRESULT.E_FAIL.
Could not test it right now, but I think that if the COM Object is in another process, all you will do is to kill your process and the COM Object may become unresponsive, waiting for your code to return from the callback function (since your process is dead already).

AccessViolationException in debugger with only managed code and WCF service

This application has a WCF web service that is called by a WinForms app. The WinForms app has a class WCFCache to manage data from the service. There is a section like this in that class to manage an optional custom configuration section that a subset of the machines have:
private bool? m_HasCustomConfiguration = null;
public bool HasCustomConfiguration
{
get
{
if (m_HasCustomConfiguration == null)
m_HasCustomConfiguration = (CustomConfiguration != null);
return (bool)m_HasCustomConfiguration;
}
}
private WCFService.CustomConfiguration m_CustomConfiguration = null;
public WCFService.CustomConfiguration CustomConfiguration
{
get
{
if (m_CustomConfiguration == null)
{
if (m_HasCustomConfiguration.HasValue
&& !m_HasCustomConfiguration.Value)
return null;
try
{
using (WCFService.WCFServiceClient wcf = new WCFService.WCFServiceClient())
{
m_CustomConfiguration =
wcf.GetCustomConfiguration(Machine.ProcessID);
// Above method returns null if no record exists.
m_HasCustomConfiguration = (m_CustomConfiguration != null);
}
} catch (Exception e) {
// Error logging & re-throw
}
}
return m_CustomConfiguration;
}
}
When I step through the debugger in code that calls either of the above properties like this:
if (!Program.WCFCache.HasCustomConfiguration)
return new List<CustomComponents>();
...it throws the following exception:
System.AccessViolationException was unhandled
Message="Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Source="System.Windows.Forms"
...
When I step onto the line containing the reference, there is a long pause, followed by a VS popup with the exception.
The exception doesn't appear when I just put a breakpoint after the above code has executed. It doesn't even appear when I put a breakpoint inside the accessors of the properties. It only occurs when I step onto a line with one of those properties from the outside. (So there is a workaround, but it can be a pain.)
Why is this happening? Can I stop it?
Edit: The whole application was written in the last year in 3.5 C#/.NET with WCF communicating between components; meaning, we don't have legacy unmanaged DLLs. Just two unmanaged calls: one to advapi32.dll when the WinForms app is loading, in the username detection procedure. The issue I'm having happens only in this one place in the code, in a place that is about as unrelated to the login section as you can get. The other is to kernel32.dll, in a GC force-flush long after anything is done with the results from calls like the one above.
Are you using any P/Invoke or other such native code? Odds are, that's where you should start looking.
This exception is a symptom of a larger problem, namely memory corruption (that what the exception says, after all). If this was a native application, you'd get a crash.
So, look at any native calls, make sure they're operating correctly, maybe run them under a debugger to try and trap the error closer to home.
Sorry, can't really give better advice given the circumstances.
I eventually found that others have encountered this situation and that it is likely a Visual Studio bug. I was using VS 2008 when the problem occurred.

Passing Unmanaged object reference to Unmanaged method in C++/CLI managed method

I am getting exception when i am trying to pass unmanaged object, to COM method in method written in managed C++/CLI class. Following is the code sample
//C++/CLI class
public ref class PSIAAdaptorManagedWrapper
{
CConfiguration *Configuration;
void InitializeConfig();
}
//C++/CLI Method implementation
void PSIAAdaptorManagedWrapper::InitializeConfig() {
Configuration = new CConfiguration();
Configuration->IPAddress = "127.0.0.1";
Configuration->UserName = "User";
Configuration->password = "password";
SomeComObject->GetInitiConfig((void *) Configuration); // Exception line
}
//signature of COM object from IDL file (observer paramer it takes is in)
[helpstring("method InitializeCameraConfig")]
HRESULT GetInitiConfig([in] void *configparam);
Above code compiles fine. But when execute I get "System.AccessViolation" runt time error on line. I think it is because, I am trying to allocate unmanaged memory in managed function. But I am not sure how to get around this.
It could be possible that a user name or password are incorrect. AccessViolation is best noted for those issues.
Also, I dont see why anything should go wrong the way you are handling things in your code above.

Categories

Resources