Date: Mon, 3 Jul 2023 23:31:53 +0300
On Mon, 3 Jul 2023 at 23:22, Patrice Roy via SG14 <sg14_at_[hidden]> wrote:
>
> Thanks Timur. I took the liberty of adding SG14 to the conversation as I think they might have some interest in this specific topic.
>
> Le lun. 3 juil. 2023 à 15:59, Timur Doumler via SG21 <sg21_at_[hidden]> a écrit :
>>
>> Hello SG21,
>>
>> Here's an issue with the current Contracts design that was brought to my attention by a user from the music technology industry, I am curious what y'all think about it.
>>
>> They are very concerned that failing contract checks, and in particular failing *asserts*, which can appear in the middle of a function body, can call a user-defined violation handler which can be defined to throw an exception. They say that basically this means that anywhere they currently have an assert somewhere deep in their library, the user can turn that assert into a throwing function, without the library knowing about it. So they would have to go off and rewrite all their library code to be exception-safe, which is an unacceptable burden to them.
>>
>> Here's a line of code with an assert in the OpenMPT library: https://github.com/OpenMPT/openmpt/blob/b6a3124344de885f08286ac17880e31247db882b/soundlib/Fastmix.cpp#L184
>>
>> Here's another assert in the same library:
>> https://github.com/OpenMPT/openmpt/blob/b6a3124344de885f08286ac17880e31247db882b/soundlib/Sndfile.cpp#L1874
>>
>> ...which is being called from here:
>> https://github.com/OpenMPT/openmpt/blob/b6a3124344de885f08286ac17880e31247db882b/soundlib/Snd_fx.cpp#L1002
>>
>> This is what the user is saying:
>>
>> "I honestly do not want to invest even a single second thinking about what state any internal data structures are in when these lines suddenly throw. That's not a part of code where we expect any exception, but when migrating the assertions to contracts, we would have to deal with any assertion potentially throwing. I could document that we do not support throwing contract violation handlers (which implies not supporting all situation specified by the C++ standard, and feels wrong), but then a C library that calls into our C++ library (supported, because we provide a facade C interface) would also need to document this, because this C library itself could end up being used by a C++ program, which could set a throwing global violation handler. Looking at the problem from another side: A global violation handler is not a orthogonal abstraction and conflicts with real-world use (i.e. libraries). I honestly do not understand why the C++ committee thinks that adding global state in 2023 is a viable solution to any problem."
>>
>> I am wondering if there is a good counter-argument to this concern? Having asserts in the middle of a function somewhere deep in the library suddenly throw an exception, if the surrounding code has never been designed with exception-safety in mind, sounds like a genuine concern for which I can't think of a good solution right now.
>>
>> The only thing that comes to mind is the line of arguing where you say that if you run into a failing assert, you're basically toast anyway, so it doesn't matter if the violation handler screws up all the invariants in your library by throwing. But somehow that doesn't sound super convincing. Unless we teach that failing asserts are not supposed to be recoverable (but on the other hand, we now also have the "observe" semantic).
>>
>> Thoughts?
Here's my thoughts and recommendations:
1) Don't migrate your C asserts (yet). The contracts facility slated
for inclusion in C++26 allows a program author to decide what the
contract violation
handling strategy is, and doesn't allow libraries to provide
library-specific strategies. So..
2) Wait with the migration until the next generation of contracts, for
which there are plans to allow such library-specific and otherwise
more local
and fine-grained strategies to be defined, so that it's not a single
global strategy.
>
> Thanks Timur. I took the liberty of adding SG14 to the conversation as I think they might have some interest in this specific topic.
>
> Le lun. 3 juil. 2023 à 15:59, Timur Doumler via SG21 <sg21_at_[hidden]> a écrit :
>>
>> Hello SG21,
>>
>> Here's an issue with the current Contracts design that was brought to my attention by a user from the music technology industry, I am curious what y'all think about it.
>>
>> They are very concerned that failing contract checks, and in particular failing *asserts*, which can appear in the middle of a function body, can call a user-defined violation handler which can be defined to throw an exception. They say that basically this means that anywhere they currently have an assert somewhere deep in their library, the user can turn that assert into a throwing function, without the library knowing about it. So they would have to go off and rewrite all their library code to be exception-safe, which is an unacceptable burden to them.
>>
>> Here's a line of code with an assert in the OpenMPT library: https://github.com/OpenMPT/openmpt/blob/b6a3124344de885f08286ac17880e31247db882b/soundlib/Fastmix.cpp#L184
>>
>> Here's another assert in the same library:
>> https://github.com/OpenMPT/openmpt/blob/b6a3124344de885f08286ac17880e31247db882b/soundlib/Sndfile.cpp#L1874
>>
>> ...which is being called from here:
>> https://github.com/OpenMPT/openmpt/blob/b6a3124344de885f08286ac17880e31247db882b/soundlib/Snd_fx.cpp#L1002
>>
>> This is what the user is saying:
>>
>> "I honestly do not want to invest even a single second thinking about what state any internal data structures are in when these lines suddenly throw. That's not a part of code where we expect any exception, but when migrating the assertions to contracts, we would have to deal with any assertion potentially throwing. I could document that we do not support throwing contract violation handlers (which implies not supporting all situation specified by the C++ standard, and feels wrong), but then a C library that calls into our C++ library (supported, because we provide a facade C interface) would also need to document this, because this C library itself could end up being used by a C++ program, which could set a throwing global violation handler. Looking at the problem from another side: A global violation handler is not a orthogonal abstraction and conflicts with real-world use (i.e. libraries). I honestly do not understand why the C++ committee thinks that adding global state in 2023 is a viable solution to any problem."
>>
>> I am wondering if there is a good counter-argument to this concern? Having asserts in the middle of a function somewhere deep in the library suddenly throw an exception, if the surrounding code has never been designed with exception-safety in mind, sounds like a genuine concern for which I can't think of a good solution right now.
>>
>> The only thing that comes to mind is the line of arguing where you say that if you run into a failing assert, you're basically toast anyway, so it doesn't matter if the violation handler screws up all the invariants in your library by throwing. But somehow that doesn't sound super convincing. Unless we teach that failing asserts are not supposed to be recoverable (but on the other hand, we now also have the "observe" semantic).
>>
>> Thoughts?
Here's my thoughts and recommendations:
1) Don't migrate your C asserts (yet). The contracts facility slated
for inclusion in C++26 allows a program author to decide what the
contract violation
handling strategy is, and doesn't allow libraries to provide
library-specific strategies. So..
2) Wait with the migration until the next generation of contracts, for
which there are plans to allow such library-specific and otherwise
more local
and fine-grained strategies to be defined, so that it's not a single
global strategy.
Received on 2023-07-03 20:32:09