I am using opengl in a MFC application in visual studio 2008.
and there my project crashes at wglmakecurrent saying:
Access violation reading location
This happens only for a certain case so this is probably not a driver issue. And also I have checked in another machine where the same error occurs.
The error occurs at wglMakeCurrent(m_hDC,m_hRC) in the following function:
void CCETIGLView::Convert2D(CPoint win, GLdouble * objx,
GLdouble * objy, GLdouble * objz)
{
if((m_hDC) && (m_hRC))
{
wglMakeCurrent(m_hDC,m_hRC);
}
The parameters are of following types:
HGLRC m_hRC;
HDC m_hDC;
Tthey are obtained from a glview class which is a child class of cview.
It returns 0 for GetLastError() when I check wglMakeCurrent function.
This happens when rendering a certain option and other options work fine.
I am using single thread therefore multi threading issue also does not count.
This test
if((m_hDC) && (m_hRC))
only makes sense if it is made sure that m_hDC and m_hRC are initialized to 0 upon class creation, so that one can actually tell, that they're initialized. Probably you're not doing this, so those variables contain non-zero garbage and hence are misinterpreted as being initialized with valid handles.
Add constant initialization to the constructor
CCETIGLView::CCETIGLView() :
m_hDC(0), m_hRC(0)
{
// ...
Related
I'm trying to write a DLL to access the C++-only method Windows.Devices.Bluetooth.BluetoothLEDevice.Close() from a C# app. I seem to be able to access the class, but Visual Studio will not build if I try to use that one method. It is shown in the member list that comes up as you type, and there is no Intellisense error, just the build error.
using namespace Windows::Devices::Bluetooth;
__declspec(dllexport) void CloseBleDeviceUnmanaged(BluetoothLEDevice^device)
{
if (device->ConnectionStatus == BluetoothConnectionStatus::Connected) //no complaints for a property
{
device->GetDeviceSelector(); //no complaints for a method either
device->Close(); //Error C2039 | 'Close': is not a member of 'Windows::Devices::Bluetooth::BluetoothLEDevice'
}
return;
}
How do I get this to at least build?
(edit: removed extraneous syntax problem as per Nico Zhu - MSFT's answer)
You don't need to do any of this to call Close from C# -- just put it in a using(...) block and it will dispose (close) the object for you automatically. If the lifetime of the objection doesn't lend itself well to a using block, you can simply call IDisposabe.Dispose() on it directly.
For the compiler error, this is documented in MSDN since you should never call Close from C++/CX:
Close methods aren't callable through Visual C++ component extensions (C++/CX) on Windows Runtime class instances where the class implemented IClosable. Instead, Visual C++ component extensions (C++/CX) code for runtime classes should call the destructor or set the last reference to null.
The parameter of CloseBleDeviceUnmanaged method is Value Type in your case. When you pass a parameter to the method. The parameter will generate a copy. And the original parameter has not been changed. Please pass the
reference type parameter like the follow.
void DevicesTool::CloseBleDeviceUnmanaged(Windows::Devices::Bluetooth::BluetoothLEDevice^device)
{
if (device->ConnectionStatus == BluetoothConnectionStatus::Connected)
{
device->GetDeviceSelector();
device->Close();
}
}
As for the Close method, I have reproduced the issue in my side(target platform version 16299), and I have report this to related team. Please pay attention to the thread update.
I have an Android app that uses NDK - a regular Android Java app with regular UI and C++ core. There are places in the core where I need to call Java methods, which means I need a JNIEnv* for that thread, which in turn means that I need to call JavaVM->AttachCurrentThread() to get the valid env.
Previously, was just doing AttachCurrentThread and didn't bother to detach at all. It worked fine in Dalvik, but ART aborts the application as soon as a thread that has called AttachCurrentThread exits without calling DetachCurrentThread. So I've read the JNI reference, and indeed it says that I must call DetachCurrentThread. But when I do that, ART aborts the app with the following message:
attempting to detach while still running code
What's the problem here, and how to call DetachCurrentThread properly?
Dalvik will also abort if the thread exits without detaching. This is implemented through a pthread key -- see threadExitCheck() in Thread.cpp.
A thread may not detach unless its call stack is empty. The reasoning behind this is to ensure that any resources like monitor locks (i.e. synchronized statements) are properly released as the stack unwinds.
The second and subsequent attach calls are, as defined by the spec, low-cost no-ops. There's no reference counting, so detach always detaches, no matter how many attaches have happened. One solution is to add your own reference-counted wrapper.
Another approach is to attach and detach every time. This is used by the app framework on certain callbacks. This wasn't so much a deliberate choice as a side-effect of wrapping Java sources around code developed primarily in C++, and trying to shoe-horn the functionality in. If you look at SurfaceTexture.cpp, particularly JNISurfaceTextureContext::onFrameAvailable(), you can see that when SurfaceTexture needs to invoke a Java-language callback function, it will attach the thread, invoke the callback, and then if the thread was just attached it will immediately detach it. The "needsDetach" flag is set by calling GetEnv to see if the thread was previously attached.
This isn't a great thing performance-wise, as each attach needs to allocate a Thread object and do some internal VM housekeeping, but it does yield the correct behavior.
I'll try a direct and practical approach (with sample code, without use of classes) answering this question for the occasional developer that came up with this error in android, in cases where they had it working and after a OS or framework update (Qt?) it started to give problems with that error and message.
JNIEXPORT void Java_com_package_class_function(JNIEnv* env.... {
JavaVM* jvm;
env->GetJavaVM(&jvm);
JNIEnv* myNewEnv; // as the code to run might be in a different thread (connections to signals for example) we will have a 'new one'
JavaVMAttachArgs jvmArgs;
jvmArgs.version = JNI_VERSION_1_6;
int attachedHere = 0; // know if detaching at the end is necessary
jint res = jvm->GetEnv((void**)&myNewEnv, JNI_VERSION_1_6); // checks if current env needs attaching or it is already attached
if (JNI_EDETACHED == res) {
// Supported but not attached yet, needs to call AttachCurrentThread
res = jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>(&myNewEnv), &jvmArgs);
if (JNI_OK == res) {
attachedHere = 1;
} else {
// Failed to attach, cancel
return;
}
} else if (JNI_OK == res) {
// Current thread already attached, do not attach 'again' (just to save the attachedHere flag)
// We make sure to keep attachedHere = 0
} else {
// JNI_EVERSION, specified version is not supported cancel this..
return;
}
// Execute code using myNewEnv
// ...
if (attachedHere) { // Key check
jvm->DetachCurrentThread(); // Done only when attachment was done here
}
}
Everything made sense after seeing the The Invocation API docs for GetEnv:
RETURNS:
If the current thread is not attached to the VM, sets *env to NULL, and returns JNI_EDETACHED. If the specified version is not supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise, sets *env to the appropriate interface, and returns JNI_OK.
Credits to:
- This question Getting error "attempting to detach while still running code" when calling JavaVm->DetachCurrentThread that in its example made it clear that it was necessary to double check every time (even though before calling detach it doesn't do it).
- #Michael that in this question comments he notes it clearly about not calling detach.
- What #fadden said: "There's no reference counting, so detach always detaches, no matter how many attaches have happened."
this is the source of the issue. My answer there was deleted with the hint to start a new question. So, here we go:
I want to pass the managed reference of this to unmanaged code. And then call the managed callback out of the unmanaged callback.
public ref class CReader
with a private field
private:
[...]
void *m_pTag;
[...]
In the constructor of the managed class I initialize the m_pTag like this:
m_pTag = new gcroot<CReader ^>(this);
Later, I pass this void *m_pTag to the unmanaged code. If the unmanaged callback is called, I'm casting the void *m_pTag back to managed reference and call the managed callback
(*(gcroot<CReader ^>*)pTag)->MANAGEDCALLBACKFUNCTION
and there is an exception thrown, if the DLL is used under another AppDomain. The Debugger stops in gcroot.h on line
// don't return T& here because & to gc pointer not yet implemented
// (T should be a pointer anyway).
T operator->() const {
// gcroot is typesafe, so use static_cast
return static_cast<T>(__VOIDPTR_TO_GCHANDLE(_handle).Target);
}
with Cannot pass a GCHandle across AppDomains.
My question is, what should I do?
Sincerly,
Sebastian
==================== EDIT ====================
I am now able to reproduce the problem. I've took some screenshots, to show the issue.
1st screenshot: constructor
snd screenshot: callback
The problem is, that the value-member of the struct gcroot in the callback is empty.
Thank you.
Sebastian
==================== EDIT ====================
Push.
The gcroot<> C++ class is a wrapper that uses the GCHandle class. The constructor calls GCHandle.ToIntPtr() to turn the handle into an opaque pointer, one that you can safely store as a member of an unmanaged struct or C++ class.
The cast then, later, converts that raw pointer back to the handle with the GCHandle.FromIntPtr() method. The GCHandle.Target property gives you the managed object reference back.
GCHandle.FromIntPtr() can indeed fail, the generic exception message is "Cannot pass a GCHandle across AppDomains". This message only fingers the common reason that this fails, it assumes that GCHandle is used in safe code and simply used incorrectly.
The message does not cover the most common reason that this fails in unsafe code. Code that invariably dies with undiagnosable exceptions due to heap corruption. In other words, the gcroot<> member of the C++ class or struct getting overwritten with an arbitrary value. Which of course dooms GCHandle.FromIntPtr(), the CLR can no longer find the handle back from a junk pointer value.
You diagnose this bug the way you diagnose any heap corruption problem. You first make sure that you get a good repro so you can trip the exception reliably. And you set a data breakpoint on the gcroot member. The debugger automatically breaks when the member is written inappropriately, the call stack gives you good idea why this happened.
I have looking at many threads about the exception "cannot pass a GCHandle across AppDomains" but I still don't get it....
I'm working with an RFID Reader which is driven by a DLL. I don't have source code for this DLL but only a sample to show how to use it.
The sample works great but I have to copy some code in another project to add the reader to the middleware Microsoft Biztalk.
The problem is that the process of Microsoft Biztalk works in another AppDomain. The reader handle events when a tag is read. But when I run it under Microsoft Biztalk I got this annoying exception.
I can't see any solution on how to make it work...
Here is some code that may be interesting :
// Let's connecting the result handlers.
// The reader calls a command-specific result handler if a command is done and the answer is ready to send.
// So let's tell the reader which functions should be called if a result is ready to send.
// result handler for reading EPCs synchronous
Reader.KSRWSetResultHandlerSyncGetEPCs(ResultHandlerSyncGetEPCs);
[...]
var readerErrorCode = Reader.KSRWSyncGetEPCs();
if (readerErrorCode == tKSRWReaderErrorCode.KSRW_REC_NoError)
{
// No error occurs while sending the command to the reader. Let's wait until the result handler was called.
if (ResultHandlerEvent.WaitOne(TimeSpan.FromSeconds(10)))
{
// The reader's work is done and the result handler was called. Let's check the result flag to make sure everything is ok.
if (_readerResultFlag == tKSRWResultFlag.KSRW_RF_NoError)
{
// The command was successfully processed by the reader.
// We'll display the result in the result handler.
}
else
{
// The command can't be proccessed by the reader. To know why check the result flag.
logger.error("Command \"KSRWSyncGetEPCs\" returns with error {0}", _readerResultFlag);
}
}
else
{
// We're getting no answer from the reader within 10 seconds.
logger.error("Command \"KSRWSyncGetEPCs\" timed out");
}
}
[...]
private static void ResultHandlerSyncGetEPCs(object sender, tKSRWResultFlag resultFlag, tKSRWExtendedResultFlag extendedResultFlag, tKSRWEPCListEntry[] epcList)
{
if (Reader == sender)
{
// Let's store the result flag in a global variable to get access from everywhere.
_readerResultFlag = resultFlag;
// Display all available epcs in the antenna field.
Console.ForegroundColor = ConsoleColor.White;
foreach (var resultListEntry in epcList)
{
handleTagEvent(resultListEntry);
}
// Let's set the event so that the calling process knows the command was processed by reader and the result is ready to get processed.
ResultHandlerEvent.Set();
}
}
You are having a problem with the gcroot<> helper class. It is used in the code that nobody can see, inside that DLL. It is frequently used by C++ code that was designed to interop with managed code, gcroot<> stores a reference to a managed object. The class uses the GCHandle type to add the reference. The GCHandle.ToIntPtr() method returns a pointer that the C++ code can store. The operation that fails is GCHandle.FromIntPtr(), used by the C++ code to recover the reference to the object.
There are two basic explanations for getting this exception:
It can be accurate. Which will happen when you initialized the code in the DLL from one AppDomain and use it in another. It isn't clear from the snippet where the Reader class object gets initialized so there are non-zero odds that this is the explanation. Be sure to keep it close to the code that uses the Reader class.
It can be caused by another bug, present in the C++ code inside the DLL. Unmanaged code often suffers from pointer bugs, the kind of bug that can accidentally overwrite memory. If that happens with the field that stores the gcroot<> object then nothing goes wrong for a while. Until the code tries to recover the object reference again. At that point the CLR notices that the corrupted pointer value no longer matches an actual object handle and generates this exception. This is certainly the hard kind of bug to solve since this happens in code you cannot fix and showing the programmer that worked on it a repro for the bug is very difficult, such memory corruption problems never repro well.
Chase bullet #1 first. There are decent odds that Biztalk runs your C# code in a separate AppDomain. And that the DLL gets loaded too soon, before or while the AppDomain is created. Something you can see with SysInternals' ProcMon. Create a repro of this by writing a little test program that creates an AppDomain and runs the test code. If that reproduces the crash then you'll have a very good way to demonstrate the issue to the RFID vendor and some hope that they'll use it and work on a fix.
Having a good working relationship with the RFID reader vendor to get to a resolution is going to be very important. That's never not a problem, always a good reason to go shopping elsewhere.
I have a weird problem regarding the use of threads inside a Firebreath plugin (in this case a FB plugin, but could happen anywhere); I will try to explain:
1) My plugin creates a thread (static), and it receives a pointer to "this" every time it gets added to a page.
2) So, now I have a thread with a pointer to the plugin, so I can call it's methods.
3) Very nice so far, BUT, suppose that I have a button (coded in HTML), which when pressed will REMOVE the current plugin, put in place another one and launch another thread.
I have described my scenario, now for the problem, when a plugin gets added it launches a thread; inside the thread there is a pointer to "this". First time, it gets fired...while the thread is executing I press the HTML button (so, the current plugin now is destroyed) and a new one is placed. The thread from the 1st plugin ends, and now returns...but it returns to the 2nd instance of the plugin.
The plugin is an image viewer, the first plugin look for a picture, it gets removed and a new one is placed; BUT the image from the 1st plugin is placed in the 2nd one. I don't know where to start looking, apparently the pointer has an address to the plugin (e.g. 12345), the plugin gets removed and instantiated again with the same memory address (12345).
Is there some way to avoid that behavior?
This is the code I have so far:
myPlugin.h
unsigned ThreadId;
HANDLE hThread;
myPlugin.cpp
unsigned __stdcall myPlugin::Thread(void *data)
{
myPlugin* this = (myPlugin*) data;
this->getImage("http:\\host.com\\image.jpg");
_endthreadex(0); //EDIT: addedd this missing line to end the thread
}
void myPlugin::onPluginReady(std::string imageUrl)
{
hThread = (HANDLE)_beginthreadex(NULL, 0, myPlugin::Thread, (void*) **this**, 0, &ThreadId);
}
void myPlugin::getImage()
{
//get an image using CURL... //no problem here
}
You need to stop and join the thread in the shutdown() function of your Plugin class; that will be called before things are actually unloaded and that will help avoid the problem.
I would also recommend using boost::thread, since FireBreath already compiles it all in, and that will help simplify some of this; you can hold a weak_ptr in your thread to the plugin class rather than passing in a void*. Of course, either way you'll need to stop and join the thread during the plugin shutdown (and the thread needs to stop quickly or the browser will get cranky about it taking so long).