Handling QMetaType registration in Qt5 with dynamic plug-ins - c++

My company is considering the jump from Qt 4.8.4 to Qt 5.4, but I came across a change that could be a showstopper for us: QMetaType::unregisterType() is removed (http://doc.qt.io/qt-5/sourcebreaks.html).
Our GUI requires plug-ins to be loaded at runtime, with the same plug-in potentially loaded and unloaded more than once during a session of the GUI. In Qt 4, we ran into an issue where when the plug-in was loaded the second time, any signal/slot that used one of the custom types registered by the plug-in would cause access violations because the meta type had been registered by the first instance of the plug-in (which was now unloaded, so the memory space was invalid). We worked around this issue by defining our own macros to register and unregister meta types safely as the plug-in was loaded and unloaded.
With QMetaType::unregisterType() no longer present, I fear that this issue will come back with no real way to solve the problem. Upgrading to Qt 5.4 would be a significant investment to even get to the point that I could test this issue, so I'm hoping I can get some indication from the experts here.
Is there any way to unregister a meta type in Qt 5? If not, does Qt 5 now have some sort of system that can detect when the DLL is being unloaded and unregister the meta types itself (highly unlikely I'd assume)? Alternatively, if we switch to the new Qt 5 signal/slot syntax, does that absolve us of the need for meta types entirely? If so, does the new syntax still allow for queued connections? Please forgive my ignorance on the subject, but I don't see it explicitly listed as supported or not.

Please forgive my ignorance on the subject, but I don't see it explicitly listed as supported or not.
This is currently unsupported, which means that do not unload plugins with Qt 5 as of writing this. Usually, you do not load and unload plugins anyway, as it is done during the launch up in general. The corresponding change in the repository also claims:
The function hasn't been working properly. It was not well tested, for example it is undefined how QVariant should behave if it contains an instance of an unregistered type.
Concept of unregistering types was inspired by plug-in system, but in most supported platforms we do not unload plug-ins.
Idea of type unregistering may block optimizations in meta object system, because it would be not possible to cache a type id. QMetaType::type() could return different ids for the same name.
Thereby, even though you thought it was working, it was unreliable which means you could have observed difficult to find bugs in its operation, resulting unreliable software on your part. I am sure you do not want to release such a software, especially if it is not recommended by the Qt Project to be used.

Related

Executable suddenly stopped working: silent exit, no errors, no nothing

I am facing a rather peculiar issue: I have a Qt C++ application that used to work fine. Now, suddenly I cannot start it anymore. No error is thrown, no nothing.
Some more information:
Last line of output when application is started in debug mode with Visual Studio 2012:
The program '[4456] App.exe' has exited with code -1 (0xffffffff).
Actual application code (= first line in main()) is never called or at least no breakpoints are triggered, so debugging is not possible.
The executable process for a few seconds appears in the process list and then disappears again.
Win 7 x64 with latest Windows updates.
The issues simultaneously appeared on two separate machines.
Application was originally built with Qt 5.2.1. Today I test-wise switched to Qt 5.4.1. But as expected no change.
No changes to source code were made. The issue also applies to existing builds of the application.
Running DependencyWalker did not yield anything of interest from my point of view.
I am flat out of ideas. Any pointers on what to try or look at? How can an executable suddenly stop working at all with no error?
I eventually found the reason for this behavior...sort of. The coding (e. g. my singletons) were never the problem (as I expected since the code always worked). Instead an external library (SAP RFC SDK) caused the troubles.
This library depends on the ICU Unicode libraries and apparently specific versions at that. Since I wasn't aware of that fact, I only had the ICU libraries that my currently used Qt version needs in my application directory. The ICU libraries for the SAP RFC SDK must have been loaded from a standard windows path so far.
In the end some software changes (Windows updates, manual application uninstalls, etc.) must have removed those libraries which resulted in that described silent fail. Simply copying the required ICU library version DLLs into my application folder, solved the issue.
The only thing I am not quite sure about, is why this was not visible when tracing the loaded DLLs via DependencyWalker.
"Actual application code (= first line in main()) is never called. So debugging is not possible."
You probably have some static storage initialization failing, that's applied before main() is called.
Do you use any interdependent singletons in your code? Consolidate them to a single singleton if so (remember, there shouldn't be more than one singleton).
Also note, debugging still is possible well for such situation, the trap is ,- for such case as described in my answer -, main()'s bodies' first line is set as the first break point as default, when you start up your program in the debugger.
Nothing hinders you to set breakpoints, that are hit before starting up the code reaches main() actually.
As for your clarification from comments:
"I do use a few singletons ..."
As mentioned above, if you are really sure you need to use a singleton, use actually a single one.
Otherwise you may end up, struggling with undefined order of initialization of static storage.
Anyway, it doesn't matter that much if static storage data depends on each other, provide a single access point to it throughout your code, to avoid cluttering it with heavy coupling to a variety of instances.
Coupling with a single instance, makes it easier to refactor the code to go with an interface, if it turns out singleton wasn't one.

Point Cloud Library's multiple-inheritance with single inheritance restriction

The C++ plugin API in which I work is bad enough without STL/exception handling but it also forbids multiple-inheritance. In other words, I can build with it if I don't mind my plugin crashing the host application on startup or I can go single and it will crash on the first direct instance of multiple inheritance in PCL (of which there is only one instance in my plugin code, but that is all it takes one supposes, and, yes, it is a required instance).
I assume that any multiple inheritances used within the PCL libs are isolated (since they appear to use this feature often) but as soon as I use something with it directly - crash.
There seem to be very few options. I can try to find another library for point cloud surface meshing with commercial usage licensing (ha!) or actually write a separate executable using PCL that is called from the plugin to do the work and pass the results back to the plugin (horrendous, platform dependent, and not an integrated solution). This entire entreprise is becoming loathsome. So much time and effort expended researching, preparing, learning, adjusting projects, carefully setting this up only to find that it won't work under these conditions.
If you have an alternative BSD library option to mention that would be great. If you think that I should go for a CL/DOS-based application to be launched to do the processing that would be great to hear arguments for as well. I support both Windows and MacOS X.
Going the external executable route. I can save the point cloud to the pcd format from the application, run the executable to load and process the file to output the results in obj format for the application to use. It is still a horrid solution but at least it works.

Edit and Continue on GDB

I know that E&C is a controversial subject and some say that it encourages a wrong approach to debugging, but still - I think we can agree that there are numerous cases when it is clearly useful - experimenting with different values of some constants, redesigning GUI parameters on-the-fly to find a good look... You name it.
My question is: Are we ever going to have E&C on GDB? I understand that it is a platform-specific feature and needs some serious cooperation with the compiler, the debugger and the OS (MSVC has this one easy as the compiler and debugger always come in one package), but... It still should be doable. I've even heard something about Apple having it implemented in their version of GCC [citation needed]. And I'd say it is indeed feasible.
Knowing all the hype about MSVC's E&C (my experience says it's the first thing MSVC users mention when asked "why not switch to Eclipse and gcc/gdb"), I'm seriously surprised that after quite some years GCC/GDB still doesn't have such feature. Are there any good reasons for that? Is someone working on it as we speak?
It is a surprisingly non-trivial amount of work, encompassing many design decisions and feature tradeoffs. Consider: you are debugging. The debugee is suspended. Its image in memory contains the object code of the source, and the binary layout of objects, the heap, the stacks. The debugger is inspecting its memory image. It has loaded debug information about the symbols, types, address mappings, pc (ip) to source correspondences. It displays the call stack, data values.
Now you want to allow a particular set of possible edits to the code and/or data, without stopping the debuggee and restarting. The simplest might be to change one line of code to another. Perhaps you recompile that file or just that function or just that line. Now you have to patch the debuggee image to execute that new line of code the next time you step over it or otherwise run through it. How does that work under the hood? What happens if the code is larger than the line of code it replaced? How does it interact with compiler optimizations? Perhaps you can only do this on a specially compiled for EnC debugging target. Perhaps you will constrain possible sites it is legal to EnC. Consider: what happens if you edit a line of code in a function suspended down in the call stack. When the code returns there does it run the original version of the function or the version with your line changed? If the original version, where does that source come from?
Can you add or remove locals? What does that do to the call stack of suspended frames? Of the current function?
Can you change function signatures? Add fields to / remove fields from objects? What about existing instances? What about pending destructors or finalizers? Etc.
There are many, many functionality details to attend to to make any kind of usuable EnC work. Then there are many cross-tools integration issues necessary to provide the infrastructure to power EnC. In particular, it helps to have some kind of repository of debug information that can make available the before- and after-edit debug information and object code to the debugger. For C++, the incrementally updatable debug information in PDBs helps. Incremental linking may help too.
Looking from the MS ecosystem over into the GCC ecosystem, it is easy to imagine the complexity and integration issues across GDB/GCC/binutils, the myriad of targets, some needed EnC specific target abstractions, and the "nice to have but inessential" nature of EnC, are why it has not appeared yet in GDB/GCC.
Happy hacking!
(p.s. It is instructive and inspiring to look at what the Smalltalk-80 interactive programming environment could do. In St80 there was no concept of "restart" -- the image and its object memory were always live, if you edited any aspect of a class you still had to keep running. In such environments object versioning was not a hypothetical.)
I'm not familiar with MSVC's E&C, but GDB has some of the things you've mentioned:
http://sourceware.org/gdb/current/onlinedocs/gdb/Altering.html#Altering
17. Altering Execution
Once you think you have found an error in your program, you might want to find out for certain whether correcting the apparent error would lead to correct results in the rest of the run. You can find the answer by experiment, using the gdb features for altering execution of the program.
For example, you can store new values into variables or memory locations, give your program a signal, restart it at a different address, or even return prematurely from a function.
Assignment: Assignment to variables
Jumping: Continuing at a different address
Signaling: Giving your program a signal
Returning: Returning from a function
Calling: Calling your program's functions
Patching: Patching your program
Compiling and Injecting Code: Compiling and injecting code in GDB
This is a pretty good reference to the old Apple implementation of "fix and continue". It also references other working implementations.
http://sources.redhat.com/ml/gdb/2003-06/msg00500.html
Here is a snippet:
Fix and continue is a feature implemented by many other debuggers,
which we added to our gdb for this release. Sun Workshop, SGI ProDev
WorkShop, Microsoft's Visual Studio, HP's wdb, and Sun's Hotspot Java
VM all provide this feature in one way or another. I based our
implementation on the HP wdb Fix and Continue feature, which they
added a few years back. Although my final implementation follows the
general outlines of the approach they took, there is almost no shared
code between them. Some of this is because of the architectual
differences (both the processor and the ABI), but even more of it is
due to implementation design differences.
Note that this capability may have been removed in a later version of their toolchain.
UPDATE: Dec-21-2012
There is a GDB Roadmap PDF presentation that includes a slide describing "Fix and Continue" among other bullet points. The presentation is dated July-9-2012 so maybe there is hope to have this added at some point. The presentation was part of the GNU Tools Cauldron 2012.
Also, I get it that adding E&C to GDB or anywhere in Linux land is a tough chore with all the different components.
But I don't see E&C as controversial. I remember using it in VB5 and VB6 and it was probably there before that. Also it's been in Office VBA since way back. And it's been in Visual Studio since VS2005. VS2003 was the only one that didn't have it and I remember devs howling about it. They intended to add it back anyway and they did with VS2005 and it's been there since. It works with C#, VB, and also C and C++. It's been in MS core tools for 20+ years, almost continuous (counting VB when it was standalone), and subtracting VS2003. But you could still say they had it in Office VBA during the VS2003 period ;)
And Jetbrains recently added it too their C# tool Rider. They bragged about it (rightly so imo) in their Rider blog.

Experience with IBPP interface for Firebird database

I'd like to the ask guys with experience in Firebird and IBPP (especially the latter). I found a lot of positive posts about Firebird but I'm having a problem to decide about IBPP. The interface itself is clean and simple but it seems that the project does not have much of activity going on (maybe because it's very stable).
Would you recommend IBPP for production environment?
Is it thread-safe?
Any known bugs?
Thanks.
In addition to the points Milan mentioned:
There is currently no way to use more than one client library when connecting to different databases, or even to specify which client library will be used. There is a certain hard-coded sequence of client library locations that are probed, and the first one that is found will be used for all connections. An IBPP version changing this has been hinted at for a very long time, but hasn't arrived yet. SVN trunk contains some code to deal with this, but I'd say that's alpha quality at most.
And all of this holds true for Windows only, as on all other platforms the Firebird client library isn't loaded at runtime anyway.
The library isn't thread-safe. That doesn't matter for the most part, as you should let each thread have its own connection, transaction and other assorted objects anyway. But IBPP uses its own smart pointer implementation, which is neither completely exception-safe nor thread-safe. Still, as long as you initialize the library from the main thread (before any other thread is created) and create and destroy IBPP objects in the same thread (so absolutely no sharing of objects with other threads!) using IBPP in multiple threads should work fine.
If you can live with the points above (they may not matter to you, at all) it is certainly ready for production use. You can always change things you run into, as we did for FlameRobin too.
IBPP is very stable and I would recommend it for production. That is, if you're going to use it for regular applications.
If you want to build an admin tool or something similar, then be prepared to go inside and get your hands dirty as some of the newer features (i.e. Firebird 2.5 stuff) that are not SQL but API improvements are not supported. For example, it is missing a layer that would expose the new trace API.
Anyway, go ahead and I use it. I have a bunch of IBPP applications in production for years, and, as Douglas wrote, FlameRobin is using IBPP and it works flawlessly (at least as far as DB layer is concerned).
The only thing to be careful about is NUMERIC fields, which are internally stored as integer+scale in Firebird. IBPP exposes those via C/C++ "double", but also via 16/32/64bit integer. So be very careful when retrieving such values, as you will get no warning. For example, if you have DECIMAL(18,2) field with value 254.00 in it, and you accidentaly read that into an integer, you will get 25400, not 254. Make sure you either read those in as double or scale yourself later. This is useful because you can safely convert 25400 to string and then add a decimal point, so you don't lose precision with double (it all depends on the kind of your application and which digits count, of course).
I can't really tell from experience because I've never used IBPP.
But apparently it's used by the flamerobin project so I'd trust it to be 'stable enough'.

Any improvements on the GCC/Windows DLLs/C++ STL front?

Yesterday, I got bit by a rather annoying crash when using DLLs compiled with GCC under Cygwin. Basically, as soon as you run with a debugger, you may end up landing in a debugging trap caused by RtlFreeHeap() receiving an address to something it did not allocate.
This is a known bug with GCC 3.4 on Cygwin. The situation arises because the libstdc++ library includes a "clever" optimization for empty strings. I spare you the details (see the references throughout this post), but whenever you allocate memory in one DLL for an std::string object that "belongs" to another DLL, you end up giving one heap a chunk to free that came from another heap. Hence the SIGTRAP in RtlFreeHeap().
There are other problems reported when exceptions are thrown across DLL boundaries.
This makes GCC 3.4 on Windows an unacceptable solution as soon as your project is based on DLLs and the STL. I have a few options to move past this option, many of which are very time-consuming and/or annoying:
I can patch my libstdc++ or rebuild it with the --enable-fully-dynamic-string configuration option
I can use static libraries instead, which increases my link time
I cannot (yet) switch to another compiler either, because of some other tools I'm using. The comments I find from some GCC people is that "it's almost never reported, so it's probably not a problem", which annoys me even more.
Does anyone have some news about this? I can't find any clear announcement that this has been fixed (the bug is still marked as "assigned"), except one comment on the GNU Radio bug tracker.
Thanks!
The general problem you're running into is that C++ was never really meant as a component language. It was really designed to be used to create complete standalone applications. Things like shared libraries and other such mechanisms were created by vendors on their own. Think of this example: suppose you created a C++ component that returns a C++ object. How is the C++ component know that it will be used by a C++ caller? And if the caller is a C++ application, why not just use the library directly?
Of course, the above information doesn't really help you.
Instead, I would create the shared libraries/DLLs such that you follow a couple of rules:
Any object created by a component is also destroyed by the same component.
A component can be safely unloaded when all of its created objects are destroyed.
You may have to create additional APIs in your component to ensure these rules, but by following these rules, it will ensure that problems like the one described won't happen.