Discussion:
Disabling exception support in QtCore?
(too old to reply)
Thiago Macieira
2013-10-01 19:20:29 UTC
Permalink
Since we decided to roll back support for exceptions in our container classes,
the only thing that currently needs exception support is the mainloop allowing
std::bad_alloc through.

Is it worth it?

Should we disable exceptions in QtCore?
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Charley Bay
2013-10-01 19:29:22 UTC
Permalink
Post by Thiago Macieira
Since we decided to roll back support for exceptions in our container classes,
the only thing that currently needs exception support is the mainloop allowing
std::bad_alloc through.
Is it worth it?
Should we disable exceptions in QtCore?
No, and yes. ;-))

I vote "not worth it, I would disable exceptions in QtCore".

--charley
Hausmann Simon
2013-10-01 19:31:05 UTC
Permalink
Hmm question - certainly worth it for sjlj platforms like 32-bit ios.

One thing I'd love to see is the ability to throw exceptions through meta-call invocations (would be useful for qml, which uses exceptions)

Simon

Fra: Thiago Macieira
Sendt: 21:20 tirsdag 1. oktober 2013
Til: ***@qt-project.org
Emne: [Development] Disabling exception support in QtCore?


Since we decided to roll back support for exceptions in our container classes,
the only thing that currently needs exception support is the mainloop allowing
std::bad_alloc through.

Is it worth it?

Should we disable exceptions in QtCore?

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Thiago Macieira
2013-10-01 21:22:06 UTC
Permalink
Post by Hausmann Simon
Hmm question - certainly worth it for sjlj platforms like 32-bit ios.
One thing I'd love to see is the ability to throw exceptions through
meta-call invocations (would be useful for qml, which uses exceptions)
The rule is: do not let exceptions propagate through Qt code.

If you call qt_metacall directly (or, better, the static version), then the
code is compiled with exceptions if they were enabled by the user code. In
that case, it's safe to throw exceptions (provided that the class of the
return type is also exception-safe).

If you use the invokeMethod() machinery, it's not thread-safe today and not
meant to be.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Knoll Lars
2013-10-01 20:00:56 UTC
Permalink
Yes, signal/slot connections between user code should IMO still be able to
pass through exceptions. I am afraid removing that will break code that's
out there.

Cheers,
Lars
Post by Hausmann Simon
Hmm question - certainly worth it for sjlj platforms like 32-bit ios.
One thing I'd love to see is the ability to throw exceptions through
meta-call invocations (would be useful for qml, which uses exceptions)
Simon
Fra: Thiago Macieira
Sendt: 21:20 tirsdag 1. oktober 2013
Emne: [Development] Disabling exception support in QtCore?
Since we decided to roll back support for exceptions in our container
classes,
the only thing that currently needs exception support is the mainloop
allowing
std::bad_alloc through.
Is it worth it?
Should we disable exceptions in QtCore?
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
_______________________________________________
Development mailing list
http://lists.qt-project.org/mailman/listinfo/development
Thiago Macieira
2013-10-01 21:23:18 UTC
Permalink
Post by Knoll Lars
Yes, signal/slot connections between user code should IMO still be able to
pass through exceptions. I am afraid removing that will break code that's
out there.
This is already forbidden since 5.0.

You can throw from your slots, if you want. If you call them directly, you're
responsible for catching the exception.

However, it's undefined behaviour if you let the exception go back to QtCore
code. The *best* you can hope for is that std::terminate is called.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
André Pönitz
2013-10-01 20:28:53 UTC
Permalink
Post by Thiago Macieira
Since we decided to roll back support for exceptions in our container classes,
the only thing that currently needs exception support is the mainloop allowing
std::bad_alloc through.
Is it worth it?
Given that hoping that std::bad_alloc is thrown when expected and hoping
that there's something that can be done about it when caught are rather
futile exercises on common systems, keeping exception support only for that
purpose does indeed not appear to be overly reasonable. So I am tempted to
say "not worth it".
Post by Thiago Macieira
Should we disable exceptions in QtCore?
Perhaps... do we have numbers how much the gain would actually be, say,
for code size?

Andre'
Thiago Macieira
2013-10-01 21:24:00 UTC
Permalink
Post by André Pönitz
Perhaps... do we have numbers how much the gain would actually be, say,
for code size?
Give me an hour.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Thiago Macieira
2013-10-01 22:30:15 UTC
Permalink
Post by André Pönitz
Perhaps... do we have numbers how much the gain would actually be, say,
for code size?
All numbers are based on my own QtCore tree, which contains a lot of patches
on top of current stable, including protected visibility. I will not test the
pristine tree.

All builds are in release mode and the libraries have been stripped of
debugging symbols (strip --strip-debug --strip-unneeded). The non-standard
flags used were:

GCC 4.7.2: -march=corei7-avx -std=c++0x -O3 -maccumulate-outgoing-args -flto
GCC 4.8:.2 (same)
ICC 14.0: -march=corei7-avx -O3 -std=c++0x
Clang 3.3: -march=corei7-avx -O3 -std=c++11
Linker flags (all compilers): -Wl,-O1 -Wl,-z,relro -Wl,--as-needed

The -O3 flag is enables optimisations that increase code size, which means this
is probably skewed. It's highly unlikely that the exceptional codepath
increases in size as much as the regular code path, though.

Findings:

- the .gcc_except_table section disappears
- the .eh_frame and .eh_frame_hdr sections remain present, with negligible
shrinkage for .eh_frame_hdr (except for ICC)
- the size of the .text section shrinks by 5.7%
- the size of the read-execute ELF segment reduces by 6.5% (same as reported
by the /usr/bin/size tool)
- the overall file size also reduces by 6.5%, which is expected since the read-
only portion of QtCore is roughly 99% of the file size. (interestingly, the
actual .text segment is only 57%)
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Christoph Feck
2013-10-01 22:04:58 UTC
Permalink
Post by Thiago Macieira
Since we decided to roll back support for exceptions in our
container classes, the only thing that currently needs exception
support is the mainloop allowing std::bad_alloc through.
Is it worth it?
Should we disable exceptions in QtCore?
If it allows us to get a backtrace actually showing where the
unhandled exception was thrown (instead of saying it was caused by the
Qt event loop), I am all for disabling exception support in QtCore.
--
Christoph Feck
http://kdepepo.wordpress.com/
KDE Quality Team
Thiago Macieira
2013-10-01 22:41:56 UTC
Permalink
Post by Christoph Feck
Post by Thiago Macieira
Since we decided to roll back support for exceptions in our
container classes, the only thing that currently needs exception
support is the mainloop allowing std::bad_alloc through.
Is it worth it?
Should we disable exceptions in QtCore?
If it allows us to get a backtrace actually showing where the
unhandled exception was thrown (instead of saying it was caused by the
Qt event loop), I am all for disabling exception support in QtCore.
In order to properly do that, we should remove all try/catch blocks in QtCore
and replace with scoped pointers and scoped values. We should let the
destructors handle the cleanup.

Turning exceptions off may or may not get you the backtrace. It may also get
you a std::terminate or a crash.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Christoph Feck
2013-10-01 23:03:19 UTC
Permalink
On quarta-feira, 2 de outubro de 2013 00:04:58, Christoph Feck
Post by Christoph Feck
Post by Thiago Macieira
Should we disable exceptions in QtCore?
If it allows us to get a backtrace actually showing where the
unhandled exception was thrown (instead of saying it was caused
by the Qt event loop), I am all for disabling exception support
in QtCore.
In order to properly do that, we should remove all try/catch blocks
in QtCore and replace with scoped pointers and scoped values. We
should let the destructors handle the cleanup.
Sounds "a bit" more work than simply disabling exceptions, so might be
something out of scope for 5.x.
Turning exceptions off may or may not get you the backtrace. It may
also get you a std::terminate or a crash.
A crash is fine, as long as I see the origin, or are you implying that
those crashes would record no backtrace at all?

For example, https://bugs.kde.org/show_bug.cgi?id=325360 shows the
backtrace of a re-thrown exception, but unless there are reproducible
steps, the report is useless, because the trace originates from the
event loop. We have hundreds of those reports, and the hope to find a
reporter who can follow linked gdb instructions is next to zero.

Christoph Feck (kdepepo)
KDE Quality Team
Thiago Macieira
2013-10-01 23:12:03 UTC
Permalink
Post by Christoph Feck
Post by Thiago Macieira
In order to properly do that, we should remove all try/catch blocks
in QtCore and replace with scoped pointers and scoped values. We
should let the destructors handle the cleanup.
Sounds "a bit" more work than simply disabling exceptions, so might be
something out of scope for 5.x.
Not really. It just takes some work to do it.
Post by Christoph Feck
Post by Thiago Macieira
Turning exceptions off may or may not get you the backtrace. It may
also get you a std::terminate or a crash.
A crash is fine, as long as I see the origin, or are you implying that
those crashes would record no backtrace at all?
They may not record anything at all. You may see only ??? in the backtrace.

This is *really* undefined behaviour territory. I can't even guess what the
ABIs do if they face a frame with no exception information.

Also note the discovery of the other email: the frame information is *still*
present in the no-exception build. So it's quite likely that the IA-64 C++ ABI
would at least manage to unwind the stack. However, after that, QtCore might
be totally and utterly useless.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Thomas Sondergaard
2013-10-02 04:57:01 UTC
Permalink
Post by Thiago Macieira
Since we decided to roll back support for exceptions in our container classes,
the only thing that currently needs exception support is the mainloop allowing
std::bad_alloc through.
Is it worth it?
Should we disable exceptions in QtCore?
As an outside voice, I'd like to point out that the rest of the world is
using exceptions and removing whatever exception support there is in
QtCore seems like a step in the wrong direction.

Regards,
Thomas
Thiago Macieira
2013-10-02 06:34:58 UTC
Permalink
Post by Thomas Sondergaard
Post by Thiago Macieira
Since we decided to roll back support for exceptions in our container
classes, the only thing that currently needs exception support is the
mainloop allowing std::bad_alloc through.
Is it worth it?
Should we disable exceptions in QtCore?
As an outside voice, I'd like to point out that the rest of the world is
using exceptions and removing whatever exception support there is in
QtCore seems like a step in the wrong direction.
That's because they use exceptions in their API. We don't use it in ours.

Also, our containers don't support types that throw exceptions. That decision
was made three months ago.

The question I posed is: given that the only remaining support is in the event
loop, that its current working status is unknown, and that it costs us an
increase of 7% in size of QtCore, is it worth it?
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
André Pönitz
2013-10-02 18:39:25 UTC
Permalink
Post by Thomas Sondergaard
Post by Thiago Macieira
Since we decided to roll back support for exceptions in our container
classes, the only thing that currently needs exception support is the
mainloop allowing std::bad_alloc through.
Is it worth it?
Should we disable exceptions in QtCore?
As an outside voice, I'd like to point out that the rest of the world is
using exceptions and removing whatever exception support there is in
QtCore seems like a step in the wrong direction.
Depends on what you define as "rest of the world".

If you mean by "rest of the world" other languages, like Java or Python,
then yes, that world is using exceptions, and they are reasonable _there_.

But if you check out what other C++ projects with Real World exposure do
you'll find that they tend to be very cautious with exceptions - unless
they simply outlaw them.

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Exceptions
is for instance pretty concise: "We don't use C++ exceptions". They later
give detailed reasoning and a conclusion including "Our advice against
using exceptions is not predicated on philosophical or moral grounds, but
practical ones." [Side note: That's _exactly_ Qt's proposition: Being
practically useful, not dogmatic.]

http://llvm.org/docs/CodingStandards.html#do-not-use-rtti-or-exceptions
says "In an effort to reduce code and executable size, LLVM does not use
RTTI (e.g. dynamic_cast<>;) or exceptions. These two language features
violate the general C++ principle of 'you only pay for what you use',
causing executable bloat even if exceptions are never used in the code
base, or if RTTI is never used for a class. Because of this, we turn them
off globally in the code."

Boost, which is not exactly notorious for "old fashioned code", says at
least on the topic of exception specifications "some compilers turn off
inlining if there is an exception-specification. Some compilers add
try/catch blocks. Such pessimizations can be a performance disaster which
makes the code unusable in practical applications" (see
http://www.boost.org/development/requirements.html#Exception-specification)

Note that even the C++ Standard rolls back a part of the previous support
for exceptions in C++11 by deprecating dynamic exception specifiers which
turned out to be (surprise...) impractical, see 15.4.17/Annex D or e.g.
http://www.gotw.ca/publications/mill22.htm for historic reasoning.

Lesson learned here: "Being allowed does not necessarily make it usable".

Size overhead for "just enabling exceptions" is (of course depending on
actual model/implementation) typically cited as 5-10%, which incidentally
matches Thiago's findings for Qt Core rather well. That's a pretty high
price for a single feature in general, and especially so if it does not add
adequate value. In my book removing the need to pay for features one
doesn't use is a Good Thing more often than not.

Andre'
Charley Bay
2013-10-02 19:00:17 UTC
Permalink
On Wed, Oct 2, 2013 at 12:39 PM, André Pönitz <
Post by André Pönitz
Post by Thomas Sondergaard
Post by Thiago Macieira
Since we decided to roll back support for exceptions in our container
classes, the only thing that currently needs exception support is the
mainloop allowing std::bad_alloc through.
Is it worth it?
Should we disable exceptions in QtCore?
As an outside voice, I'd like to point out that the rest of the world is
using exceptions and removing whatever exception support there is in
QtCore seems like a step in the wrong direction.
Depends on what you define as "rest of the world".
If you mean by "rest of the world" other languages, like Java or Python,
then yes, that world is using exceptions, and they are reasonable _there_.
But if you check out what other C++ projects with Real World exposure do
you'll find that they tend to be very cautious with exceptions - unless
they simply outlaw them.
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Exceptions
is for instance pretty concise: "We don't use C++ exceptions". They later
give detailed reasoning and a conclusion including "Our advice against
using exceptions is not predicated on philosophical or moral grounds, but
practical ones." [Side note: That's _exactly_ Qt's proposition: Being
practically useful, not dogmatic.]
http://llvm.org/docs/CodingStandards.html#do-not-use-rtti-or-exceptions
says "In an effort to reduce code and executable size, LLVM does not use
RTTI (e.g. dynamic_cast<>;) or exceptions. These two language features
violate the general C++ principle of 'you only pay for what you use',
causing executable bloat even if exceptions are never used in the code
base, or if RTTI is never used for a class. Because of this, we turn them
off globally in the code."
Boost, which is not exactly notorious for "old fashioned code", says at
least on the topic of exception specifications "some compilers turn off
inlining if there is an exception-specification. Some compilers add
try/catch blocks. Such pessimizations can be a performance disaster which
makes the code unusable in practical applications" (see
http://www.boost.org/development/requirements.html#Exception-specification
)
Note that even the C++ Standard rolls back a part of the previous support
for exceptions in C++11 by deprecating dynamic exception specifiers which
turned out to be (surprise...) impractical, see 15.4.17/Annex D or e.g.
http://www.gotw.ca/publications/mill22.htm for historic reasoning.
Lesson learned here: "Being allowed does not necessarily make it usable".
Size overhead for "just enabling exceptions" is (of course depending on
actual model/implementation) typically cited as 5-10%, which incidentally
matches Thiago's findings for Qt Core rather well. That's a pretty high
price for a single feature in general, and especially so if it does not add
adequate value. In my book removing the need to pay for features one
doesn't use is a Good Thing more often than not.
Andre'
+1 to Andre'

I didn't trim his post because there's a lot there, and IMHO it's worth
re-reading.

--charley
Thiago Macieira
2013-10-02 19:40:29 UTC
Permalink
Post by André Pönitz
Size overhead for "just enabling exceptions" is (of course depending on
actual model/implementation) typically cited as 5-10%, which incidentally
matches Thiago's findings for Qt Core rather well. That's a pretty high
price for a single feature in general, and especially so if it does not add
adequate value. In my book removing the need to pay for features one
doesn't use is a Good Thing more often than not.
Here's an interesting thought:

What if the compiler would not intersperse the exception handler code with
normal code? Right now, each generated function contains all the exceptional
code paths from all cases, including inlined functions. If you read the
disassembly of any C++ library, you'll see something like:

function1:
prologue
body of the function
epilogue (including return)
exception code
function2:
prologue
body of the function
epilogue (including return)
exception code

That means the increase of 5-10% in code size on disk is translated a 5-10%
increase in RAM usage too. What if all those "exception code" blocks were
moved elsewhere?

In that case, the increase on disk size might not be the same as the increase
in RAM size. The exceptional code would be paged in only in case exceptions
did actually get thrown.

This is just a thought experiment.

To implement it, we'd need an exception format that allowed two or more
separate bodies for a function, a compiler option or pragma to tell the
compiler that exceptions are unlikely, and a linker that cooperates.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Marc Mutz
2013-10-03 07:43:18 UTC
Permalink
On 2013-10-02 20:39, André Pönitz wrote:
[...]
Post by André Pönitz
tp://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Exceptions
is for instance pretty concise: "We don't use C++ exceptions". They later
give detailed reasoning and a conclusion including "Our advice against
using exceptions is not predicated on philosophical or moral grounds, but
practical ones." [Side note: That's _exactly_ Qt's proposition: Being
practically useful, not dogmatic.]
http://llvm.org/docs/CodingStandards.html#do-not-use-rtti-or-exceptions
says "In an effort to reduce code and executable size, LLVM does not use
RTTI (e.g. dynamic_cast<>;) or exceptions. These two language features
violate the general C++ principle of 'you only pay for what you use',
causing executable bloat even if exceptions are never used in the code
base, or if RTTI is never used for a class. Because of this, we turn them
off globally in the code."
Quoting style guides that apply for applications can by definition not
contain reasoning for library writers. Apps live in their own little
dream world and can play with the compiler flags anyway they wish. They
only target one App, after all, and if they switch off exceptions or
RTTI, no user user will care. Yes, LLVM also provides libraries. But
they're narrowly-focused and, what's more important, they're toolkits,
not frameworks. Meaning they don't force a particular structure on your
program. Yes, there are probably checkers that use the LLVM libraries as
a framework, but now we're really leaving the realm of general-purpose
libraries and are comparing apples and oranges.

My pov on this whole discussion is this:

Qt is a general-purpose framework library. As a library, its *only*
purpose is to serve its users; as a framework, it mandates a certain
structure on programs using it. As a general-purpose library, it can
only assume very little about how users of the library use the library.

If those users want to use exceptions, which is still a standard C++
feature, last I checked, Qt should go out its way to enable those users,
while at the same time giving users that _don't_ want exceptions a way
to switch them off. Forcing users of Qt to choose between not using
exceptions at all or writing try/catch blocks around the bodies of *all
of their slots*, because we removed the single spot where (buggily)
escaped exceptions could be centrally dealt with (main), is preposterous
at best and arrogant at worst.

IMO, we should support throwing exceptions through the event loop. We
don't (yet) have to guarantee that you can later re-enter the event loop
again, even though that's a valid mid-term goal.

At the same time, there should be an easy way to build Qt with exception
support disabled, for those apps that don't want to handle their errors.

Uhh, so there's the problem with Linux and The Single Distribution Build
To Rule Them All. So what? Build separate libraries. Were doing so for
debug support, too, and once upon a time, we did so for threads, until
we found we want to use them in Qt, too, and started requiring them.
Where are exceptions different?

(As an aside: I just need to bring up Bjarne's quote from GoingNative
this year where he - convincingly, I might add - argues that in every
comparison of exception overhead, what is really being compared is code
that handles all errors in a defined way (assuming at least the Basic
Exception Guarantee is implemented in code) vs. code that handles no or
only selected errors. IIRC, he goes on to say that equivalent code
without exceptions would have both a higher runtime as well as a higher
maintenance cost than the exception-using code. Incidentally, that's the
guy that argued for -what?- 20 years that exceptions can be implemented
with zero runtime overhead in the non-throwing case until Windows AMD64
finally implemented it that way, so I would not dare to dismiss this
data point lightly).

Other than that I can only +1 what Olivier already said about testing,
incl. offering help.
Post by André Pönitz
Boost, which is not exactly notorious for "old fashioned code", says at
least on the topic of exception specifications "some compilers turn off
inlining if there is an exception-specification. Some compilers add
try/catch blocks. Such pessimizations can be a performance disaster which
makes the code unusable in practical applications" (see
://www.boost.org/development/requirements.html#Exception-specification)
Note that even the C++ Standard rolls back a part of the previous support
for exceptions in C++11 by deprecating dynamic exception specifiers which
turned out to be (surprise...) impractical, see 15.4.17/Annex D or e.g.
http://www.gotw.ca/publications/mill22.htm for historic reasoning.
Lesson learned here: "Being allowed does not necessarily make it usable".
I strongly oppose use criticism of C++98 exception specifications to
argue against exception support. That is such a fundamental logic error,
I don't even know how to rebuke it politely :)
Thiago Macieira
2013-10-03 18:08:32 UTC
Permalink
Post by Marc Mutz
Qt is a general-purpose framework library. As a library, its *only*
purpose is to serve its users; as a framework, it mandates a certain
structure on programs using it. As a general-purpose library, it can
only assume very little about how users of the library use the library.
If those users want to use exceptions, which is still a standard C++
feature, last I checked, Qt should go out its way to enable those users,
while at the same time giving users that _don't_ want exceptions a way
to switch them off.
I am assuming you mean "users who want to use exceptions in their own code".
That explicitly rules out using exceptions when interacting with Qt code. The
only grey area is template code when used with a type from the user.

Requiring a third-party library to support exceptions when they don't care is
like asking a C library to support exceptions. Please point me to any
discussion in Glib or APR or other generic C frameworks about them becoming
exception-safe. Until then, we retain the right to make a decision whether
exceptions can travel through our code, despite our choice of coding in C++.

Our current decision is that they can't.
Post by Marc Mutz
Forcing users of Qt to choose between not using
exceptions at all or writing try/catch blocks around the bodies of *all
of their slots*, because we removed the single spot where (buggily)
escaped exceptions could be centrally dealt with (main), is preposterous
at best and arrogant at worst.
I disagree.

First, we establish an API contract. We provide the boundaries for which the
API works and how it works, inside those boundaries. If you violate the
boundaries, undefined behaviour occurs.

Let's say, for the sake of argument, that one of those boundaries is that you
will not throw back to Qt code. And let's assume developers are following that
guidance, to the best of their knowledge. If an exception escapes because of a
bug in the user code, then it's a BUG. All discussion about how things should
behave is already out of the window.

In addition, I also dispute the usefulness of a global try/catch in main().
What good is it to know that std::bad_cast or std::system_error happened, if
you don't know where or what caused it? You're not going to display an error
message to the user, there's nothing the user can do to correct the problem.
You might say one would want to log the information for a developer to
correct, but the catch block is too late already -- the stack has been
unwound. The best thing you can actually have is a std::terminate() with a
proper core dump.
Post by Marc Mutz
IMO, we should support throwing exceptions through the event loop. We
don't (yet) have to guarantee that you can later re-enter the event loop
again, even though that's a valid mid-term goal.
And IMO, we shouldn't have to. I maintain that event-driven programming is
incompatible with exceptions.

Unless you can answer this question: what exceptions can a mouse press
generate?
Post by Marc Mutz
Uhh, so there's the problem with Linux and The Single Distribution Build
To Rule Them All. So what? Build separate libraries. Were doing so for
debug support, too, and once upon a time, we did so for threads, until
we found we want to use them in Qt, too, and started requiring them.
Where are exceptions different?
When Qt is part of the system API, there's only one Qt in the system.

Choices are only available to application developers who bundle Qt with their
applications. That's the feature system.

When you have to interact with an existing system API, such as on Blackberry
or Jolla or Ubuntu Phone devices, or on a KDE system, you don't have an
option. Qt comes with the system, pre-built. You don't get to ask "my
application doesn't use threads or QProcess or QFileSystemWatcher, so please
remove QThread from Qt".
Post by Marc Mutz
(As an aside: I just need to bring up Bjarne's quote from GoingNative
this year where he - convincingly, I might add - argues that in every
comparison of exception overhead, what is really being compared is code
that handles all errors in a defined way (assuming at least the Basic
Exception Guarantee is implemented in code) vs. code that handles no or
only selected errors. IIRC, he goes on to say that equivalent code
without exceptions would have both a higher runtime as well as a higher
maintenance cost than the exception-using code. Incidentally, that's the
guy that argued for -what?- 20 years that exceptions can be implemented
with zero runtime overhead in the non-throwing case until Windows AMD64
finally implemented it that way, so I would not dare to dismiss this
data point lightly).
Thanks for the parentheses.

But it's orthogonal to the discussion. Our numbers stand: 7% increase in code
size because exceptions are enabled, on top of the non-exceptional error
handling that already exists.

Maybe the 7% is caused by our not having "noexcept" everywhere.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Alex Malyushytskyy
2013-10-04 00:11:54 UTC
Permalink
Assuming exceptions are enabled for signal/slots what is going to happen
with Qt::QueuedConnection?
As far as I understand at this point you can't catch exception in the
signal.
That means you will have to do it in the event loop. What is going to
happen next? Re-throw it and an uncaught exception again?

In this case I would prefer to make sure exception never leaves the slot.

Alex




On Thu, Oct 3, 2013 at 11:08 AM, Thiago Macieira
Post by Thiago Macieira
Post by Marc Mutz
Qt is a general-purpose framework library. As a library, its *only*
purpose is to serve its users; as a framework, it mandates a certain
structure on programs using it. As a general-purpose library, it can
only assume very little about how users of the library use the library.
If those users want to use exceptions, which is still a standard C++
feature, last I checked, Qt should go out its way to enable those users,
while at the same time giving users that _don't_ want exceptions a way
to switch them off.
I am assuming you mean "users who want to use exceptions in their own code".
That explicitly rules out using exceptions when interacting with Qt code. The
only grey area is template code when used with a type from the user.
Requiring a third-party library to support exceptions when they don't care is
like asking a C library to support exceptions. Please point me to any
discussion in Glib or APR or other generic C frameworks about them becoming
exception-safe. Until then, we retain the right to make a decision whether
exceptions can travel through our code, despite our choice of coding in C++.
Our current decision is that they can't.
Post by Marc Mutz
Forcing users of Qt to choose between not using
exceptions at all or writing try/catch blocks around the bodies of *all
of their slots*, because we removed the single spot where (buggily)
escaped exceptions could be centrally dealt with (main), is preposterous
at best and arrogant at worst.
I disagree.
First, we establish an API contract. We provide the boundaries for which the
API works and how it works, inside those boundaries. If you violate the
boundaries, undefined behaviour occurs.
Let's say, for the sake of argument, that one of those boundaries is that you
will not throw back to Qt code. And let's assume developers are following that
guidance, to the best of their knowledge. If an exception escapes because of a
bug in the user code, then it's a BUG. All discussion about how things should
behave is already out of the window.
In addition, I also dispute the usefulness of a global try/catch in main().
What good is it to know that std::bad_cast or std::system_error happened, if
you don't know where or what caused it? You're not going to display an error
message to the user, there's nothing the user can do to correct the problem.
You might say one would want to log the information for a developer to
correct, but the catch block is too late already -- the stack has been
unwound. The best thing you can actually have is a std::terminate() with a
proper core dump.
Post by Marc Mutz
IMO, we should support throwing exceptions through the event loop. We
don't (yet) have to guarantee that you can later re-enter the event loop
again, even though that's a valid mid-term goal.
And IMO, we shouldn't have to. I maintain that event-driven programming is
incompatible with exceptions.
Unless you can answer this question: what exceptions can a mouse press
generate?
Post by Marc Mutz
Uhh, so there's the problem with Linux and The Single Distribution Build
To Rule Them All. So what? Build separate libraries. Were doing so for
debug support, too, and once upon a time, we did so for threads, until
we found we want to use them in Qt, too, and started requiring them.
Where are exceptions different?
When Qt is part of the system API, there's only one Qt in the system.
Choices are only available to application developers who bundle Qt with their
applications. That's the feature system.
When you have to interact with an existing system API, such as on Blackberry
or Jolla or Ubuntu Phone devices, or on a KDE system, you don't have an
option. Qt comes with the system, pre-built. You don't get to ask "my
application doesn't use threads or QProcess or QFileSystemWatcher, so please
remove QThread from Qt".
Post by Marc Mutz
(As an aside: I just need to bring up Bjarne's quote from GoingNative
this year where he - convincingly, I might add - argues that in every
comparison of exception overhead, what is really being compared is code
that handles all errors in a defined way (assuming at least the Basic
Exception Guarantee is implemented in code) vs. code that handles no or
only selected errors. IIRC, he goes on to say that equivalent code
without exceptions would have both a higher runtime as well as a higher
maintenance cost than the exception-using code. Incidentally, that's the
guy that argued for -what?- 20 years that exceptions can be implemented
with zero runtime overhead in the non-throwing case until Windows AMD64
finally implemented it that way, so I would not dare to dismiss this
data point lightly).
Thanks for the parentheses.
But it's orthogonal to the discussion. Our numbers stand: 7% increase in code
size because exceptions are enabled, on top of the non-exceptional error
handling that already exists.
Maybe the 7% is caused by our not having "noexcept" everywhere.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
_______________________________________________
Development mailing list
http://lists.qt-project.org/mailman/listinfo/development
Thiago Macieira
2013-10-04 01:38:44 UTC
Permalink
Post by Alex Malyushytskyy
Assuming exceptions are enabled for signal/slots what is going to happen
with Qt::QueuedConnection?
As far as I understand at this point you can't catch exception in the
signal.
If we choose to standardise that exceptions are allowed from slots and they
propagate back to the emitter, that will still only apply to direct
connections.

Any type of queued connection (blocking or not) is totally and utterly
incompatible with exceptions. Throw from a slot that was called via a queued
connection and it's now the event loop that will catch it.

At that point we enter the other argument: are exceptions allowed to travel
through the event loop code? If we decide that they aren't, then this is
undefined behaviour and the application is allowed to crash.

If we decide that they are, then the event loop will exit, returning the
control back to the caller of exec(), potentially terminating the thread or
the application if run() or main() don't catch it.
Post by Alex Malyushytskyy
That means you will have to do it in the event loop. What is going to
happen next? Re-throw it and an uncaught exception again?
In this case I would prefer to make sure exception never leaves the slot.
That's my argument.

To summarise:

1) exceptions causing the event loop to exit do not make sense. The API to
make the event loop to exit is quit(), not an exception. Besides, I question
the usefulness of a global try/catch in main() or around an event loop.

2) given (1), exceptions must never be thrown from a slot that was called via
QueuedConnection or BlockingQueuedConnection.

3) given (2), if we allowed exceptions, users would have to take care that
they are thrown only during DirectConnection. That implies that (potentially
other) users must know which exceptions every slot throws, so that they can
decide whether they can connect to a given signal or connect via queued
connections. Therefore, I would advise against this, but I will not put strong
opposition against it.

4) if we decide to build QtCore with exception support after all, I would
agree that invokeMethod() should be strongly exception-safe, though I am not
volunteering to write that code, review it or bugfix it; though as a maintainer
I might be called into fixing it if it falls into bitrot.

The questions now are:
a) do we have volunteers to write the code, unit tests and documentation for
direct connection slot throws, and maintain it?
b) is the cost worth the effort?

To answer (b), I'd like someone to test our major platforms to see what
happens when an exception is thrown through code built with -fno-exceptions.
Given that the .eh_frame sections are still present, there's a chance that it
*works*. See also -funwind-tables.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Mandeep Sandhu
2013-10-04 05:12:46 UTC
Permalink
On Fri, Oct 4, 2013 at 7:08 AM, Thiago Macieira
Post by Thiago Macieira
Post by Alex Malyushytskyy
Assuming exceptions are enabled for signal/slots what is going to happen
with Qt::QueuedConnection?
As far as I understand at this point you can't catch exception in the
signal.
If we choose to standardise that exceptions are allowed from slots and they
propagate back to the emitter, that will still only apply to direct
connections.
Any type of queued connection (blocking or not) is totally and utterly
incompatible with exceptions. Throw from a slot that was called via a queued
connection and it's now the event loop that will catch it.
At that point we enter the other argument: are exceptions allowed to travel
through the event loop code? If we decide that they aren't, then this is
undefined behaviour and the application is allowed to crash.
If we decide that they are, then the event loop will exit, returning the
control back to the caller of exec(), potentially terminating the thread or
the application if run() or main() don't catch it.
Post by Alex Malyushytskyy
That means you will have to do it in the event loop. What is going to
happen next? Re-throw it and an uncaught exception again?
In this case I would prefer to make sure exception never leaves the slot.
That's my argument.
1) exceptions causing the event loop to exit do not make sense. The API to
make the event loop to exit is quit(), not an exception. Besides, I question
the usefulness of a global try/catch in main() or around an event loop.
2) given (1), exceptions must never be thrown from a slot that was called via
QueuedConnection or BlockingQueuedConnection.
3) given (2), if we allowed exceptions, users would have to take care that
they are thrown only during DirectConnection. That implies that (potentially
other) users must know which exceptions every slot throws, so that they can
decide whether they can connect to a given signal or connect via queued
connections. Therefore, I would advise against this, but I will not put strong
opposition against it.
+1 to that.

Though my opinion is that if we _have_ to have exceptions then don't make
exceptions to where they can apply (pun intended!:)), like only to
signal-slots that too with DirectConnection, otherwise it starts looking
like a 'caveat' that users must remember. If possible, it should be either
ALL or nothing.

Also, is it so difficult to write code which is a mix of both, i.e
interacting with libs which have exceptions and also with those that don't?
I bet there's already a lot of s/w out there that uses libraries written by
ppl from these 2 different schools of thought.

(I've mostly been a "user" of Qt and have written my applications on
embedded systems w/o feeling the need for exceptions, though my opinion
might be biased as I came from a C programming background where we were
used on the good ol' way of checking return values of fxns)

-mandeep
Kurt Pattyn
2013-10-04 05:34:10 UTC
Permalink
In some markets like Avionics and Defense, it is simply forbidden for us to use exceptions.
So, at least I think it should be possible to disable them in Qt if it was decided to allow them, otherwise we would be forced to use another framework.
Aside from that, and that is personal, I really like having exception free code. Signals are a much nicer alternative, AND we can run tests to see if they are all connected (again a requirement from the Avionics world: all errors must be explicitly handled). With exceptions this is much more difficult, if not impossible. Besides that, using exceptions can lead to some very strange, difficult to detect bugs, especially in applications having an event loop, and multiple threads.

So, a +1 from me to avoid exceptions.
Post by Mandeep Sandhu
Post by Thiago Macieira
Post by Alex Malyushytskyy
Assuming exceptions are enabled for signal/slots what is going to happen
with Qt::QueuedConnection?
As far as I understand at this point you can't catch exception in the
signal.
If we choose to standardise that exceptions are allowed from slots and they
propagate back to the emitter, that will still only apply to direct
connections.
Any type of queued connection (blocking or not) is totally and utterly
incompatible with exceptions. Throw from a slot that was called via a queued
connection and it's now the event loop that will catch it.
At that point we enter the other argument: are exceptions allowed to travel
through the event loop code? If we decide that they aren't, then this is
undefined behaviour and the application is allowed to crash.
If we decide that they are, then the event loop will exit, returning the
control back to the caller of exec(), potentially terminating the thread or
the application if run() or main() don't catch it.
Post by Alex Malyushytskyy
That means you will have to do it in the event loop. What is going to
happen next? Re-throw it and an uncaught exception again?
In this case I would prefer to make sure exception never leaves the slot.
That's my argument.
1) exceptions causing the event loop to exit do not make sense. The API to
make the event loop to exit is quit(), not an exception. Besides, I question
the usefulness of a global try/catch in main() or around an event loop.
2) given (1), exceptions must never be thrown from a slot that was called via
QueuedConnection or BlockingQueuedConnection.
3) given (2), if we allowed exceptions, users would have to take care that
they are thrown only during DirectConnection. That implies that (potentially
other) users must know which exceptions every slot throws, so that they can
decide whether they can connect to a given signal or connect via queued
connections. Therefore, I would advise against this, but I will not put strong
opposition against it.
+1 to that.
Though my opinion is that if we _have_ to have exceptions then don't make exceptions to where they can apply (pun intended!:)), like only to signal-slots that too with DirectConnection, otherwise it starts looking like a 'caveat' that users must remember. If possible, it should be either ALL or nothing.
Also, is it so difficult to write code which is a mix of both, i.e interacting with libs which have exceptions and also with those that don't? I bet there's already a lot of s/w out there that uses libraries written by ppl from these 2 different schools of thought.
(I've mostly been a "user" of Qt and have written my applications on embedded systems w/o feeling the need for exceptions, though my opinion might be biased as I came from a C programming background where we were used on the good ol' way of checking return values of fxns)
-mandeep
Nicolás Alvarez
2013-10-04 05:44:33 UTC
Permalink
Post by Kurt Pattyn
In some markets like Avionics and Defense, it is simply forbidden for us to use exceptions.
So, at least I think it should be possible to disable them in Qt if it was
decided to allow them, otherwise we would be forced to use another
framework.
There's no way we would go from the current debates about whether
exceptions should be allowed at all, to making exceptions *mandatory*.
That will never happen.
--
Nicolás
Marc Mutz
2013-10-04 07:17:25 UTC
Permalink
Post by Kurt Pattyn
In some markets like Avionics and Defense, it is simply forbidden for us to use exceptions.
The only reason to forbid exceptions on technical (as opposed to
uneducated or -worse- political) grounds is in hard real-time systems,
because throwing an exception doesn't have a deterministic runtime in
current implementations. But neither do malloc and operator new, so you
will find that they tend to get banned together. I doubt that Qt will be
used in a hard real-time environment with banned dynamic allocations
anytime soon :)

Thanks,
Marc
Olivier Goffart
2013-10-05 18:38:45 UTC
Permalink
Post by Thiago Macieira
Post by Alex Malyushytskyy
Assuming exceptions are enabled for signal/slots what is going to happen
with Qt::QueuedConnection?
As far as I understand at this point you can't catch exception in the
signal.
If we choose to standardise that exceptions are allowed from slots and they
propagate back to the emitter, that will still only apply to direct
connections.
Any type of queued connection (blocking or not) is totally and utterly
incompatible with exceptions. Throw from a slot that was called via a queued
connection and it's now the event loop that will catch it.
At that point we enter the other argument: are exceptions allowed to travel
through the event loop code? If we decide that they aren't, then this is
undefined behaviour and the application is allowed to crash.
If we decide that they are, then the event loop will exit, returning the
control back to the caller of exec(), potentially terminating the thread or
the application if run() or main() don't catch it.
Post by Alex Malyushytskyy
That means you will have to do it in the event loop. What is going to
happen next? Re-throw it and an uncaught exception again?
In this case I would prefer to make sure exception never leaves the slot.
That's my argument.
1) exceptions causing the event loop to exit do not make sense. The API to
make the event loop to exit is quit(), not an exception. Besides, I question
the usefulness of a global try/catch in main() or around an event loop.
2) given (1), exceptions must never be thrown from a slot that was called
via QueuedConnection or BlockingQueuedConnection.
3) given (2), if we allowed exceptions, users would have to take care that
they are thrown only during DirectConnection. That implies that (potentially
other) users must know which exceptions every slot throws, so that they can
decide whether they can connect to a given signal or connect via queued
connections. Therefore, I would advise against this, but I will not put
strong opposition against it.
4) if we decide to build QtCore with exception support after all, I would
agree that invokeMethod() should be strongly exception-safe, though I am not
volunteering to write that code, review it or bugfix it; though as a
maintainer I might be called into fixing it if it falls into bitrot.
a) do we have volunteers to write the code, unit tests and documentation
for direct connection slot throws, and maintain it?
b) is the cost worth the effort?
To answer (b), I'd like someone to test our major platforms to see what
happens when an exception is thrown through code built with -fno-exceptions.
Given that the .eh_frame sections are still present, there's a chance that
it *works*. See also -funwind-tables.
I do volounteer:
That part of the code is already exception safe so the only thing to do is to
have the unit test.

Unit tests are there:
https://codereview.qt-project.org/67361
https://codereview.qt-project.org/67362

For the documentation, I would refer to Mitch's old attempt.
https://codereview.qt-project.org/41179
(I presonally think this explain too much, but well)
--
Olivier

Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
Knoll Lars
2013-10-02 05:42:24 UTC
Permalink
Post by Thiago Macieira
Post by Knoll Lars
Yes, signal/slot connections between user code should IMO still be able
to
pass through exceptions. I am afraid removing that will break code
that's
out there.
This is already forbidden since 5.0.
Is there any good reason why we don't support this, as we did in Qt 4? My
goal of still compiling Qt Core with exceptions enabled was to allow for
exactly this use case.

Lars
Post by Thiago Macieira
You can throw from your slots, if you want. If you call them directly,
you're
responsible for catching the exception.
However, it's undefined behaviour if you let the exception go back to
QtCore
code. The *best* you can hope for is that std::terminate is called.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Thiago Macieira
2013-10-02 06:32:00 UTC
Permalink
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
Yes, signal/slot connections between user code should IMO still be able
to
pass through exceptions. I am afraid removing that will break code
that's
out there.
This is already forbidden since 5.0.
Is there any good reason why we don't support this, as we did in Qt 4? My
goal of still compiling Qt Core with exceptions enabled was to allow for
exactly this use case.
Because we don't test it, so there's no guarantee that it works. In fact, I'd
be surprised if it works at all. What's more, our types aren't exception-safe,
even the container types. It's entirely unknown what will happen during a
stack unwind.

Personally, I don't want to maintain that functionality.

And then there's the question: is it worth the 7% increase in code size?
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Olivier Goffart
2013-10-02 07:09:16 UTC
Permalink
Post by Thiago Macieira
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
Yes, signal/slot connections between user code should IMO still be able
to pass through exceptions. I am afraid removing that will break code
that's out there.
This is already forbidden since 5.0.
Is there any good reason why we don't support this, as we did in Qt 4? My
goal of still compiling Qt Core with exceptions enabled was to allow for
exactly this use case.
Because we don't test it, so there's no guarantee that it works. In fact,
I'd be surprised if it works at all. What's more, our types aren't
exception-safe, even the container types. It's entirely unknown what will
happen during a stack unwind.
Personally, I don't want to maintain that functionality.
And then there's the question: is it worth the 7% increase in code size?
It is working. We even got bug report for some corner case where it did not,
and I fixed those. (so they are used)
There is no test because you did not want to have one. But we could easily add
more auto tests. (It is really not that difficult)
And it is "forbidden" only because you decided so, but it is not actually
forbidden.

I personally think letting exception go from the slot to the signal is a good
feature (for the DirectConnection case).
I am willing to maintain this functionality.

Of course it is not allowed to throw an exception with QueuedConnection, or if
the caller of the signal is not exception safe (all signals in Qt).
And if a signal is connected to several slots, further slots are not going to
be called.

The only stack frame it needs to crosses are QMetaObject::activate, the moc
generated code for signals or qt_metacall, and the templated helpers in
qobject(defs)_impl.h. Could we perhaps only compile part of QtCore with
exception support?

Exceptions are not only about std::bad_alloc.
I think it is unfortunuate that we removed support for user thrown exceptions
from our container. (I agree that supporting bad_alloc is useless).
But supporting throwing constructor and copy constructor in all the containers
is a bit harder than in signals and slots. (And also less usefull)

--
Olivier

Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
Nowacki Jedrzej
2013-10-02 10:51:59 UTC
Permalink
Hi,

(sorry for top posting)

Small note, I believe that exception safety never really worked. It was almost not tested, so everyone depending on the feature was depending on an undefined behavior anyway. At the beginning of Qt5 I tried to improve the situation in our containers. I wrote a few tests, I fixed a few bugs, but it was like going through a swamp, slow and dirty. Getting a review was difficult, because such changes were increasing code size, binary size, were complex and the worst almost nobody cared. The amount of bugs was scary. Even our the best container QVector was not working correctly with exceptions. So removing exception support is not a functionality regression it is just acknowledging of the current state. Now, maybe in some places it works, but from a API user perspective it is gambling. I do not think we are able to have exception safety "back", that requires a lot of commitment that I do not see.

Personally, I used to like exceptions. It is sad that Qt is not supporting or really use them, but I believe that people can live without such support.

std::bad_alloc, is it even possible to see it, when at least on Linux most of distros have memory overcommit enabled?

Cheers,
Jędrek
________________________________________
Od: development-bounces+jedrzej.nowacki=***@qt-project.org [development-bounces+jedrzej.nowacki=***@qt-project.org] w imieniu Olivier Goffart [***@woboq.com]
Wysłano: 2 października 2013 09:09
Do: ***@qt-project.org
Cc: Thiago Macieira
Temat: Re: [Development] Disabling exception support in QtCore?
Post by Thiago Macieira
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
Yes, signal/slot connections between user code should IMO still be able
to pass through exceptions. I am afraid removing that will break code
that's out there.
This is already forbidden since 5.0.
Is there any good reason why we don't support this, as we did in Qt 4? My
goal of still compiling Qt Core with exceptions enabled was to allow for
exactly this use case.
Because we don't test it, so there's no guarantee that it works. In fact,
I'd be surprised if it works at all. What's more, our types aren't
exception-safe, even the container types. It's entirely unknown what will
happen during a stack unwind.
Personally, I don't want to maintain that functionality.
And then there's the question: is it worth the 7% increase in code size?
It is working. We even got bug report for some corner case where it did not,
and I fixed those. (so they are used)
There is no test because you did not want to have one. But we could easily add
more auto tests. (It is really not that difficult)
And it is "forbidden" only because you decided so, but it is not actually
forbidden.

I personally think letting exception go from the slot to the signal is a good
feature (for the DirectConnection case).
I am willing to maintain this functionality.

Of course it is not allowed to throw an exception with QueuedConnection, or if
the caller of the signal is not exception safe (all signals in Qt).
And if a signal is connected to several slots, further slots are not going to
be called.

The only stack frame it needs to crosses are QMetaObject::activate, the moc
generated code for signals or qt_metacall, and the templated helpers in
qobject(defs)_impl.h. Could we perhaps only compile part of QtCore with
exception support?

Exceptions are not only about std::bad_alloc.
I think it is unfortunuate that we removed support for user thrown exceptions
from our container. (I agree that supporting bad_alloc is useless).
But supporting throwing constructor and copy constructor in all the containers
is a bit harder than in signals and slots. (And also less usefull)

--
Olivier

Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
Thiago Macieira
2013-10-02 16:32:12 UTC
Permalink
Post by Olivier Goffart
It is working. We even got bug report for some corner case where it did
not, and I fixed those. (so they are used)
There is no test because you did not want to have one. But we could easily
add more auto tests. (It is really not that difficult)
And it is "forbidden" only because you decided so, but it is not actually
forbidden.
Circular definition. We agreed that it wasn't going to be supported, so I
didn't want a test for something that we were allowed to break.

We test the API contract, not the implementation.

if we change our agreement that certain exceptions are allowed, then the tests
for those conditions would be allowed.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Knoll Lars
2013-10-02 07:13:11 UTC
Permalink
Post by Olivier Goffart
Post by Thiago Macieira
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
Yes, signal/slot connections between user code should IMO still be
able
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
to pass through exceptions. I am afraid removing that will break
code
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
that's out there.
This is already forbidden since 5.0.
Is there any good reason why we don't support this, as we did in Qt
4? My
Post by Knoll Lars
goal of still compiling Qt Core with exceptions enabled was to allow
for
Post by Knoll Lars
exactly this use case.
Because we don't test it, so there's no guarantee that it works. In
fact,
I'd be surprised if it works at all. What's more, our types aren't
exception-safe, even the container types. It's entirely unknown what
will
happen during a stack unwind.
Personally, I don't want to maintain that functionality.
And then there's the question: is it worth the 7% increase in code size?
It is working. We even got bug report for some corner case where it did
not,
and I fixed those. (so they are used)
There is no test because you did not want to have one. But we could
easily add
more auto tests. (It is really not that difficult)
And it is "forbidden" only because you decided so, but it is not actually
forbidden.
I personally think letting exception go from the slot to the signal is a
good
feature (for the DirectConnection case).
I am willing to maintain this functionality.
Of course it is not allowed to throw an exception with QueuedConnection,
or if
the caller of the signal is not exception safe (all signals in Qt).
And if a signal is connected to several slots, further slots are not
going to
be called.
The only stack frame it needs to crosses are QMetaObject::activate, the
moc
generated code for signals or qt_metacall, and the templated helpers in
qobject(defs)_impl.h. Could we perhaps only compile part of QtCore with
exception support?
Exceptions are not only about std::bad_alloc.
I think it is unfortunuate that we removed support for user thrown
exceptions
from our container. (I agree that supporting bad_alloc is useless).
But supporting throwing constructor and copy constructor in all the
containers
is a bit harder than in signals and slots. (And also less usefull)
+1. It's our decision not to use exceptions in Qt code, but I see quite a
bit of value in being able to throw exceptions from a slot if that's the
pattern a developer chooses to use. We've been doing quite a bit of work
to allow this in Qt 4, and it's the main place where exception safety in
Qt Core really makes sense IMO.

Cheers,
Lars
Harri Porten
2013-10-02 07:55:02 UTC
Permalink
Post by Knoll Lars
+1. It's our decision not to use exceptions in Qt code, but I see quite a
bit of value in being able to throw exceptions from a slot if that's the
pattern a developer chooses to use. We've been doing quite a bit of work
to allow this in Qt 4, and it's the main place where exception safety in
Qt Core really makes sense IMO.
I plea for keeping this part working as well. Just thinking about very
concrete real world code that relies on it.

Harri.
Thiago Macieira
2013-10-02 16:30:58 UTC
Permalink
Post by Knoll Lars
+1. It's our decision not to use exceptions in Qt code, but I see quite a
bit of value in being able to throw exceptions from a slot if that's the
pattern a developer chooses to use. We've been doing quite a bit of work
to allow this in Qt 4, and it's the main place where exception safety in
Qt Core really makes sense IMO.
Then please clarify the semantics. I really don't see this as a currently-
valid use-case because it's not been specified.

I dislike allowing this via the signal-slot mechanism because I see throwing
from a slot as incompatible with the connection semantics. That would mean any
signal could throw ANY exception. It would also preempt the execution of
further slots, which might be important.

Usually the person who connects a signal to a slot is a completely different
developer than who wrote the signal or the slot. That would mean people who do
connections should have to pay attention to what slots throw and know what
signals can cope with exceptions being thrown.

I would accept at most exceptions through the invokeMethod mechanism in a
DirectConnection, since that's a 1:1 relationship and there are no signals.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Olivier Goffart
2013-10-03 08:36:44 UTC
Permalink
Post by Thiago Macieira
Post by Knoll Lars
+1. It's our decision not to use exceptions in Qt code, but I see quite a
bit of value in being able to throw exceptions from a slot if that's the
pattern a developer chooses to use. We've been doing quite a bit of work
to allow this in Qt 4, and it's the main place where exception safety in
Qt Core really makes sense IMO.
Then please clarify the semantics. I really don't see this as a currently-
valid use-case because it's not been specified.
I dislike allowing this via the signal-slot mechanism because I see throwing
from a slot as incompatible with the connection semantics.
That would mean any signal could throw ANY exception. It would also preempt
the execution of further slots, which might be important.
Usually the person who connects a signal to a slot is a completely different
developer than who wrote the signal or the slot.
I think your assumptions are false.
When using signals and slot in an application one write both the signal and
the slot at the same time, to wire two part of that same appliation.
Post by Thiago Macieira
That would mean people who do connections should have to pay attention to
what slots throw and know what signals can cope with exceptions being
thrown.
Signals and slots are not different from normal functions in that respect
(especially virtual functions)
One need to take care who calls your function when you throw exceptions.
Post by Thiago Macieira
I would accept at most exceptions through the invokeMethod mechanism in a
DirectConnection, since that's a 1:1 relationship and there are no signals.
--
Olivier

Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
Julien Blanc
2013-10-03 09:10:21 UTC
Permalink
Post by Olivier Goffart
Post by Thiago Macieira
That would mean any signal could throw ANY exception. It would also preempt
the execution of further slots, which might be important.
Usually the person who connects a signal to a slot is a completely different
developer than who wrote the signal or the slot.
I think your assumptions are false.
When using signals and slot in an application one write both the signal and
the slot at the same time, to wire two part of that same appliation.
This may be true in a (small) application, but definitely not if you are
developping a library. Usually, you write signals but don’t have any
clue about the slots that will be connected to.
Post by Olivier Goffart
Post by Thiago Macieira
That would mean people who do connections should have to pay attention to
what slots throw and know what signals can cope with exceptions being
thrown.
Signals and slots are not different from normal functions in that respect
(especially virtual functions)
One need to take care who calls your function when you throw exceptions.
That would mean that both slots and signals needs to document which
exception they can respectively throw/handle. With qt5 we gained static
checking of signal/slot compatibility. Introducing exceptions here would
ruin this gain, since it will introduce a new way for signal and slots
to be incompatible.

And i don’t know how you can reasonably catch an exception in an
asynchronous call.

IMHO, slots should be nothrow.
Post by Olivier Goffart
Post by Thiago Macieira
I would accept at most exceptions through the invokeMethod mechanism in a
DirectConnection, since that's a 1:1 relationship and there are no signals.
+1. Exceptions outside DirectConnection would be very strange animals.

Julien
Thiago Macieira
2013-10-03 17:38:59 UTC
Permalink
Post by Olivier Goffart
Post by Thiago Macieira
I dislike allowing this via the signal-slot mechanism because I see
throwing from a slot as incompatible with the connection semantics.
That would mean any signal could throw ANY exception. It would also preempt
the execution of further slots, which might be important.
Usually the person who connects a signal to a slot is a completely
different developer than who wrote the signal or the slot.
I think your assumptions are false.
When using signals and slot in an application one write both the signal and
the slot at the same time, to wire two part of that same appliation.
That's not at all true. If it were, we wouldn't have signals or slots in our
public API. If people were supposed to write the signals and the slots they
connect, all our signals and slots would be private.

Since we have public signals and public slots and other libraries do the same,
it stands to reason that a third-party is expected to connect them. Moreover,
it stands to reason that a third-party might connect a fourth-party slot to
one of our (first-party) signals.

Said slot must not throw. Period.
Post by Olivier Goffart
Post by Thiago Macieira
That would mean people who do connections should have to pay attention to
what slots throw and know what signals can cope with exceptions being
thrown.
Signals and slots are not different from normal functions in that respect
(especially virtual functions)
One need to take care who calls your function when you throw exceptions.
I agree.

Which is why I am saying that we need to establish rules for when exceptions
would be allowed to escape a slot.

Right now, our rule is: Qt code is noexcept. If your slot throws when called
by Qt, the behaviour is undefined. If it throws when something else calls it,
we make no statements.

If you want to change that rule, then we can discuss it.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Olivier Goffart
2013-10-10 12:53:50 UTC
Permalink
Post by Thiago Macieira
Post by Olivier Goffart
Post by Thiago Macieira
I dislike allowing this via the signal-slot mechanism because I see
throwing from a slot as incompatible with the connection semantics.
That would mean any signal could throw ANY exception. It would also preempt
the execution of further slots, which might be important.
Usually the person who connects a signal to a slot is a completely
different developer than who wrote the signal or the slot.
I think your assumptions are false.
When using signals and slot in an application one write both the signal and
the slot at the same time, to wire two part of that same appliation.
That's not at all true. If it were, we wouldn't have signals or slots in our
public API. If people were supposed to write the signals and the slots they
connect, all our signals and slots would be private.
I did not said that the signal and the slot were always written by the same
person. And I explicitly said for an application, and you are talking about
libraries.
Post by Thiago Macieira
Since we have public signals and public slots and other libraries do the
same, it stands to reason that a third-party is expected to connect them.
Moreover, it stands to reason that a third-party might connect a
fourth-party slot to one of our (first-party) signals.
Your logic is flawed. The fact that some signals cannot be connected to slots
that do not throw exceptions does not implies that no signals can be connected
to slot that throw exceptions.

When developing an application, developer who throw exceptionshould know what
they are doing. It is not allowed to connect a signal from a exception unsafe
class to a slot that may throw exception.
But if they know that the class is exception safe, it should be allowed for
them to connect signal from this class to slots that throw exceptions.
Post by Thiago Macieira
Post by Olivier Goffart
Post by Thiago Macieira
That would mean people who do connections should have to pay attention to
what slots throw and know what signals can cope with exceptions being
thrown.
Signals and slots are not different from normal functions in that respect
(especially virtual functions)
One need to take care who calls your function when you throw exceptions.
I agree.
Which is why I am saying that we need to establish rules for when exceptions
would be allowed to escape a slot.
Right now, our rule is: Qt code is noexcept. If your slot throws when called
by Qt, the behaviour is undefined. If it throws when something else calls
it, we make no statements.
If you want to change that rule, then we can discuss it.
I want to change that rule.

Unles specified here, Qt code is noexcept.
The only places where exceptions are allowed are:
- Exceptions thrown by a slot are propagated to the signal connected with
direct connection
- Exceptions propagated through a call to invokeMethod are propagated from
the method to the call
- Exceptions thrown from QtConcurrent will be by re thrown when calling the
QFuture API if the exception is a subclass of QException

(Did I miss something?)
--
Olivier

Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
André Somers
2013-10-10 13:14:02 UTC
Permalink
Post by Olivier Goffart
Post by Thiago Macieira
Post by Olivier Goffart
Post by Thiago Macieira
I dislike allowing this via the signal-slot mechanism because I see
throwing from a slot as incompatible with the connection semantics.
That would mean any signal could throw ANY exception. It would also preempt
the execution of further slots, which might be important.
Usually the person who connects a signal to a slot is a completely
different developer than who wrote the signal or the slot.
I think your assumptions are false.
When using signals and slot in an application one write both the signal and
the slot at the same time, to wire two part of that same appliation.
That's not at all true. If it were, we wouldn't have signals or slots in our
public API. If people were supposed to write the signals and the slots they
connect, all our signals and slots would be private.
I did not said that the signal and the slot were always written by the same
person. And I explicitly said for an application, and you are talking about
libraries.
Even for applications this statement is nonsense. For all but trivial
applications that during their lifetime only get worked on by a single
developer, the likelyhood of the same person always writing the slots
for every signal goes to 0 rapidly with the age and number of developers
on a project.

André
--
You like Qt?
I am looking for collegues to join me at i-Optics!
Olivier Goffart
2013-10-10 13:25:42 UTC
Permalink
Post by André Somers
Post by Olivier Goffart
Post by Thiago Macieira
Post by Olivier Goffart
Post by Thiago Macieira
I dislike allowing this via the signal-slot mechanism because I see
throwing from a slot as incompatible with the connection semantics.
That would mean any signal could throw ANY exception. It would also preempt
the execution of further slots, which might be important.
Usually the person who connects a signal to a slot is a completely
different developer than who wrote the signal or the slot.
I think your assumptions are false.
When using signals and slot in an application one write both the signal and
the slot at the same time, to wire two part of that same appliation.
That's not at all true. If it were, we wouldn't have signals or slots in
our public API. If people were supposed to write the signals and the
slots they connect, all our signals and slots would be private.
I did not said that the signal and the slot were always written by the same
person. And I explicitly said for an application, and you are talking
about libraries.
Even for applications this statement is nonsense. For all but trivial
applications that during their lifetime only get worked on by a single
developer, the likelyhood of the same person always writing the slots
for every signal goes to 0 rapidly with the age and number of developers
on a project.
That's not what I said.
And regardless, I don't think it has any relevance for the problem in
question.

Within a code base that uses exception, developers should know which part of
the code is exception safe and which part of the code can throw exception.
And they know they should not call a function that can throw an exception from
code that is not exception safe. (Hence they don't connect a signal from code
that is not exception safe to a slot that throw an exception)
--
Olivier

Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
BRM
2013-10-10 15:22:44 UTC
Permalink
Post by Olivier Goffart
Post by André Somers
Post by Olivier Goffart
Post by Thiago Macieira
Post by Olivier Goffart
Post by Thiago Macieira
I dislike allowing this via the signal-slot mechanism because I see
throwing from a slot as incompatible with the connection semantics.
That would mean any signal could throw ANY exception. It would also preempt
the execution of further slots, which might be important.
Usually the person who connects a signal to a slot is a completely
different developer than who wrote the signal or the slot.
I think your assumptions are false.
When using signals and slot in an application one write both the signal and
the slot at the same time, to wire two part of that same appliation.
That's not at all true. If it were, we wouldn't have signals or slots in
our public API. If people were supposed to write the signals and the
slots they connect, all our signals and slots would be private.
I did not said that the signal and the slot were always written by the same
person.  And I explicitly said for an application, and you are talking
about libraries.
Even for applications this statement is nonsense. For all but trivial
applications that during their lifetime only get worked on by a single
developer, the likelyhood of the same person always writing the slots
for every signal goes to 0 rapidly with the age and number of developers
on a project.
That's not what I said.
It may not have been what you said, but it is what would occur.
Post by Olivier Goffart
And regardless, I don't think it has any relevance for the problem in
question.
Quite relevant.
 
Post by Olivier Goffart
Within a code base that uses exception, developers should know which part of
the code is exception safe and which part of the code can throw exception. 
And they know they should not call a function that can throw an exception from
code that is not exception safe. (Hence they don't connect a signal from code
that is not exception safe to a slot that throw an exception)
So now you have to a wrapper slot to wrap exceptions for any object from a library
that you may interact with, or potentially any other code in your own project.

I have personnally maintained a 400k+ SLOC codebase based on QT.
It made extensive use of Signals/Slots between objects. Even though I was
pretty much the only developer working on it, I still had to quite often track
through signals/slots to make sure I understood things. Not because the codebase
was unclear, but because it was quite non-trivial. It would have been an extensive
PITA to try to know which ones I could or could not use exceptions with.

I'm no compiler expert - but without help from the compiler to make sure that kind
of things doesn't happen - e.g. marking signals/slots as Q_EXCEPTION_THROW
and Q_EXCEPTION_SAFE and having some part of the compiler chain detect
and at minimal warn of issues - it will not be feasible.

$0.02

Ben
Olivier Goffart
2013-10-10 16:02:38 UTC
Permalink
Post by BRM
I have personnally maintained a 400k+ SLOC codebase based on QT.
It made extensive use of Signals/Slots between objects. Even though I was
pretty much the only developer working on it, I still had to quite often
track through signals/slots to make sure I understood things. Not because
the codebase was unclear, but because it was quite non-trivial. It would
have been an extensive PITA to try to know which ones I could or could not
use exceptions with.
I'm no compiler expert - but without help from the compiler to make sure
that kind of things doesn't happen - e.g. marking signals/slots as
Q_EXCEPTION_THROW and Q_EXCEPTION_SAFE and having some part of the compiler
chain detect and at minimal warn of issues - it will not be feasible.
Programming is not easy.
Now, our goal is to make programming with Qt as easy as possible.

Tell me what makes programming easier:

1) We forbid any use of exception in any slot connected to any signal.
- Programmers that don't use exceptions don't care because it does not
impact them.
- Programmers that uses exception in their application to forward errors
cannot use signals and slots to propagate exceptions from one object of their
application to another anymore.

2) We allow slots to forward the exception to the signal.
- Programmers that don't use exceptions still don't care because it does
not impact them.
- Programmers that use exceptions can hapilly let exceptions go from the
slot to where the signal is emitted.


If you are not using exception now as I understand from your text above, then
nothing changes for you.

However, someone who is using currently exceptions, they will have to change
their code for more complicated code because we decided to forbid it ("for
their own good")

May I recall that exceptions through signals and slots always worked, and was
used. And now you need to give a good reason to forbid it.
Reducing the size of QtCore might be a good reason, but just saying "it's for
your own good" is not.
--
Olivier

Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
Thiago Macieira
2013-10-10 15:58:37 UTC
Permalink
Post by Olivier Goffart
- Exceptions thrown by a slot are propagated to the signal connected with
direct connection
- Exceptions propagated through a call to invokeMethod are propagated from
the method to the call
- Exceptions thrown from QtConcurrent will be by re thrown when
calling the QFuture API if the exception is a subclass of QException
Just adding one more thing:
- despite the fact that the signal-slot mechanism propagates exceptions,
*all* Qt signal emitters are noexcept, so throwing from a slot when called by
a signal emitter inside Qt is undefined behaviour.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Knoll Lars
2013-10-02 10:54:36 UTC
Permalink
Post by Nowacki Jedrzej
Hi,
(sorry for top posting)
Small note, I believe that exception safety never really worked. It
was almost not tested, so everyone depending on the feature was depending
on an undefined behavior anyway. At the beginning of Qt5 I tried to
improve the situation in our containers. I wrote a few tests, I fixed a
few bugs, but it was like going through a swamp, slow and dirty. Getting
a review was difficult, because such changes were increasing code size,
binary size, were complex and the worst almost nobody cared. The amount
of bugs was scary. Even our the best container QVector was not working
correctly with exceptions. So removing exception support is not a
functionality regression it is just acknowledging of the current state.
Now, maybe in some places it works, but from a API user perspective it is
gambling. I do not think we are able to have exception safety "back",
that requires a lot of commitment that I do not see.
I don't think anybody is asking to have exception safety for our
containers. All we're talking about right now is signal/slot connections.

Cheers,
Lars
Post by Nowacki Jedrzej
Personally, I used to like exceptions. It is sad that Qt is not
supporting or really use them, but I believe that people can live without
such support.
std::bad_alloc, is it even possible to see it, when at least on Linux
most of distros have memory overcommit enabled?
Cheers,
Jędrek
________________________________________
Wysłano: 2 października 2013 09:09
Cc: Thiago Macieira
Temat: Re: [Development] Disabling exception support in QtCore?
Post by Thiago Macieira
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
Yes, signal/slot connections between user code should IMO still be
able
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
to pass through exceptions. I am afraid removing that will break
code
Post by Knoll Lars
Post by Thiago Macieira
Post by Knoll Lars
that's out there.
This is already forbidden since 5.0.
Is there any good reason why we don't support this, as we did in Qt
4? My
Post by Knoll Lars
goal of still compiling Qt Core with exceptions enabled was to allow
for
Post by Knoll Lars
exactly this use case.
Because we don't test it, so there's no guarantee that it works. In
fact,
I'd be surprised if it works at all. What's more, our types aren't
exception-safe, even the container types. It's entirely unknown what
will
happen during a stack unwind.
Personally, I don't want to maintain that functionality.
And then there's the question: is it worth the 7% increase in code size?
It is working. We even got bug report for some corner case where it did
not,
and I fixed those. (so they are used)
There is no test because you did not want to have one. But we could
easily add
more auto tests. (It is really not that difficult)
And it is "forbidden" only because you decided so, but it is not actually
forbidden.
I personally think letting exception go from the slot to the signal is a
good
feature (for the DirectConnection case).
I am willing to maintain this functionality.
Of course it is not allowed to throw an exception with QueuedConnection,
or if
the caller of the signal is not exception safe (all signals in Qt).
And if a signal is connected to several slots, further slots are not
going to
be called.
The only stack frame it needs to crosses are QMetaObject::activate, the
moc
generated code for signals or qt_metacall, and the templated helpers in
qobject(defs)_impl.h. Could we perhaps only compile part of QtCore with
exception support?
Exceptions are not only about std::bad_alloc.
I think it is unfortunuate that we removed support for user thrown
exceptions
from our container. (I agree that supporting bad_alloc is useless).
But supporting throwing constructor and copy constructor in all the
containers
is a bit harder than in signals and slots. (And also less usefull)
--
Olivier
Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
_______________________________________________
Development mailing list
http://lists.qt-project.org/mailman/listinfo/development
_______________________________________________
Development mailing list
http://lists.qt-project
Carlos Duclos
2013-10-03 10:30:34 UTC
Permalink
(sorry for jumping in the middle of the discussion)
Post by Marc Mutz
Quoting style guides that apply for applications can by definition not
contain reasoning for library writers. Apps live in their own little
dream world and can play with the compiler flags anyway they wish. They
only target one App, after all, and if they switch off exceptions or
RTTI, no user user will care. Yes, LLVM also provides libraries. But
they're narrowly-focused and, what's more important, they're toolkits,
not frameworks. Meaning they don't force a particular structure on your
program. Yes, there are probably checkers that use the LLVM libraries as
a framework, but now we're really leaving the realm of general-purpose
libraries and are comparing apples and oranges.
Qt is a general-purpose framework library. As a library, its *only*
purpose is to serve its users; as a framework, it mandates a certain
structure on programs using it. As a general-purpose library, it can
only assume very little about how users of the library use the library.
If those users want to use exceptions, which is still a standard C++
feature, last I checked, Qt should go out its way to enable those users,
while at the same time giving users that _don't_ want exceptions a way
to switch them off. Forcing users of Qt to choose between not using
exceptions at all or writing try/catch blocks around the bodies of *all
of their slots*, because we removed the single spot where (buggily)
escaped exceptions could be centrally dealt with (main), is preposterous
at best and arrogant at worst.
I'm not so sure if I follow your logic here, but Qt does not necessarily need to just blindly
provide everything the users might want. In this case I think that the benefits Qt will get
out of having two separate code paths for supporting and not supporting exceptions are not
enough to justify having those two code paths in the first place (and I think a large part of the audience
leans that way too).
Post by Marc Mutz
IMO, we should support throwing exceptions through the event loop. We
don't (yet) have to guarantee that you can later re-enter the event loop
again, even though that's a valid mid-term goal.
Throwing exceptions without having a way to safely reenter the event loop is not very desirable.
It is the equivalent of being able to change the wheels in your car while driving it but not being able
to steer the car while doing it. In my book that is a big no-no.

If exception support is deemed necessary then that should be solved before the discussion continues.
Post by Marc Mutz
At the same time, there should be an easy way to build Qt with exception
support disabled, for those apps that don't want to handle their errors.
Uhh, so there's the problem with Linux and The Single Distribution Build
To Rule Them All. So what? Build separate libraries. Were doing so for
debug support, too, and once upon a time, we did so for threads, until
we found we want to use them in Qt, too, and started requiring them.
Where are exceptions different?
If you look at things under that light, they are not that different. But there is the underlying difference
that exceptions will produce out of order code paths that might produce subtle problems that might take
years to discover and fix. Debug symbols are easy, you either have them or not. Threads are even easier, you can build
a library with thread support and the same code will work without modifications if you remove thread support (well, mostly).
Exceptions on the other hand will require us to be able to assure that we can contain them safely _OR_ that we tell users
that they need to wait for unexpected exceptions.

The problem with exceptions is that there is no middle ground, as with for instance libc signals. You either start throwing them
and catching them or you don't. This proposal is just to make the latter the default case, which makes sense in my view.
Kurt Pattyn
2013-10-03 10:33:40 UTC
Permalink
I can add to this that Google also disallows exceptions, as is stated in their style guide: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Exceptions#Exceptions
So, Qt is not alone in this regard.
Subject: Re: [Development] Disabling exception support in QtCore?
Date: 3 Oct 2013 11:10:21 GMT+02:00
Post by Olivier Goffart
Post by Thiago Macieira
That would mean any signal could throw ANY exception. It would also preempt
the execution of further slots, which might be important.
Usually the person who connects a signal to a slot is a completely different
developer than who wrote the signal or the slot.
I think your assumptions are false.
When using signals and slot in an application one write both the signal and
the slot at the same time, to wire two part of that same appliation.
This may be true in a (small) application, but definitely not if you are developping a library. Usually, you write signals but don’t have any clue about the slots that will be connected to.
Post by Olivier Goffart
Post by Thiago Macieira
That would mean people who do connections should have to pay attention to
what slots throw and know what signals can cope with exceptions being
thrown.
Signals and slots are not different from normal functions in that respect
(especially virtual functions)
One need to take care who calls your function when you throw exceptions.
That would mean that both slots and signals needs to document which exception they can respectively throw/handle. With qt5 we gained static checking of signal/slot compatibility. Introducing exceptions here would ruin this gain, since it will introduce a new way for signal and slots to be incompatible.
And i don’t know how you can reasonably catch an exception in an asynchronous call.
IMHO, slots should be nothrow.
Post by Olivier Goffart
Post by Thiago Macieira
I would accept at most exceptions through the invokeMethod mechanism in a
DirectConnection, since that's a 1:1 relationship and there are no signals.
+1. Exceptions outside DirectConnection would be very strange animals.
Julien
Knoll Lars
2013-10-10 16:46:55 UTC
Permalink
Post by Olivier Goffart
Post by BRM
I have personnally maintained a 400k+ SLOC codebase based on QT.
It made extensive use of Signals/Slots between objects. Even though I
was
pretty much the only developer working on it, I still had to quite often
track through signals/slots to make sure I understood things. Not
because
the codebase was unclear, but because it was quite non-trivial. It would
have been an extensive PITA to try to know which ones I could or could
not
use exceptions with.
I'm no compiler expert - but without help from the compiler to make sure
that kind of things doesn't happen - e.g. marking signals/slots as
Q_EXCEPTION_THROW and Q_EXCEPTION_SAFE and having some part of the
compiler
chain detect and at minimal warn of issues - it will not be feasible.
Programming is not easy.
Now, our goal is to make programming with Qt as easy as possible.
1) We forbid any use of exception in any slot connected to any signal.
- Programmers that don't use exceptions don't care because it does
not
impact them.
- Programmers that uses exception in their application to forward
errors
cannot use signals and slots to propagate exceptions from one object of
their
application to another anymore.
2) We allow slots to forward the exception to the signal.
- Programmers that don't use exceptions still don't care because it
does
not impact them.
- Programmers that use exceptions can hapilly let exceptions go from
the
slot to where the signal is emitted.
If you are not using exception now as I understand from your text above,
then
nothing changes for you.
However, someone who is using currently exceptions, they will have to
change
their code for more complicated code because we decided to forbid it
("for
their own good")
May I recall that exceptions through signals and slots always worked, and
was
used. And now you need to give a good reason to forbid it.
Reducing the size of QtCore might be a good reason, but just saying
"it's for
your own good" is not.
Agree with Olivier.

Let's keep the level of support we had in Qt 4.x for throwing exceptions
from slots:

* It's undefined behaviour unless the place that emits the signal is
prepared to catch the exception.
* If a slot throws, no further slots connected to the signal will get
called
* throwing from any place that's connected to a signal defined in the Qt
libraries leads to undefined behaviour

The size reduction of QtCore is not a valid argument IMO. First of all
we're talking about a number below 10%, and secondly this number could be
reduced to almost 0 by making the build system for Qt Core only compile a
few selected files with exception support enabled.

Cheers,
Lars
Alex Malyushytskyy
2013-10-10 20:54:09 UTC
Permalink
Post by Knoll Lars
Post by Olivier Goffart
However, someone who is using currently exceptions, they will have to change
their code for more complicated code because we decided to forbid it ("for
their own good")
Post by Knoll Lars
Post by Olivier Goffart
May I recall that exceptions through signals and slots always worked, and was
used.


It never worked.with other than direct connections.
As I see it there is a simple choice either to provide indirect connections
or propagate exceptions to signal.
Otherwise you always have to assume that every slot is called the way you
can't let exception leave slot anyway.

Alex
Post by Knoll Lars
Post by Olivier Goffart
Post by BRM
I have personnally maintained a 400k+ SLOC codebase based on QT.
It made extensive use of Signals/Slots between objects. Even though I was
pretty much the only developer working on it, I still had to quite often
track through signals/slots to make sure I understood things. Not because
the codebase was unclear, but because it was quite non-trivial. It would
have been an extensive PITA to try to know which ones I could or could not
use exceptions with.
I'm no compiler expert - but without help from the compiler to make sure
that kind of things doesn't happen - e.g. marking signals/slots as
Q_EXCEPTION_THROW and Q_EXCEPTION_SAFE and having some part of the compiler
chain detect and at minimal warn of issues - it will not be feasible.
Programming is not easy.
Now, our goal is to make programming with Qt as easy as possible.
1) We forbid any use of exception in any slot connected to any signal.
- Programmers that don't use exceptions don't care because it does not
impact them.
- Programmers that uses exception in their application to forward errors
cannot use signals and slots to propagate exceptions from one object of their
application to another anymore.
2) We allow slots to forward the exception to the signal.
- Programmers that don't use exceptions still don't care because it does
not impact them.
- Programmers that use exceptions can hapilly let exceptions go from the
slot to where the signal is emitted.
If you are not using exception now as I understand from your text above, then
nothing changes for you.
However, someone who is using currently exceptions, they will have to change
their code for more complicated code because we decided to forbid it ("for
their own good")
May I recall that exceptions through signals and slots always worked, and was
used. And now you need to give a good reason to forbid it.
Reducing the size of QtCore might be a good reason, but just saying "it's for
your own good" is not.
Agree with Olivier.
Let's keep the level of support we had in Qt 4.x for throwing exceptions
* It's undefined behaviour unless the place that emits the signal is
prepared to catch the exception.
* If a slot throws, no further slots connected to the signal will get
called
* throwing from any place that's connected to a signal defined in the Qt
libraries leads to undefined behaviour
The size reduction of QtCore is not a valid argument IMO. First of all
we're talking about a number below 10%, and secondly this number could be
reduced to almost 0 by making the build system for Qt Core only compile a
few selected files with exception support enabled.
Cheers,
Lars
_______________________________________________
Development mailing list
http://lists.qt-project.org/mailman/listinfo/development
Thiago Macieira
2013-10-10 23:07:55 UTC
Permalink
Post by Alex Malyushytskyy
It never worked.with other than direct connections.
As I see it there is a simple choice either to provide indirect connections
or propagate exceptions to signal. Otherwise you always have to assume that
every slot is called the way you can't let exception leave slot anyway.
I don't mind complex rules. If anyone wants to use this feature, they have to
know how it works.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Continue reading on narkive:
Loading...