Program logic bugs vs input/environmental errors

Dicebot via Digitalmars-d digitalmars-d at puremagic.com
Sun Nov 9 13:12:16 PST 2014


On Monday, 3 November 2014 at 03:29:05 UTC, Walter Bright wrote:
> On 11/2/2014 3:44 PM, Dicebot wrote:
>>> They have hardware protection against sharing memory between 
>>> processes. It's a
>>> reasonable level of protection.
>> reasonable default - yes
>> reasoable level of protection in general - no
>
> No language can help when that is the requirement.

Yes, because it is property of system architecture as a whole 
which is exactly what I am speaking about.

> It is absolutely different because of scale; having 1K of 
> shared memory is very different from having 100Mb shared 
> between processes including the stack and program code.

It is possible to have minimal amount shared mutable memory 
inside one process. There is nothing inherently blocking one to 
do so, same as there is nothing inherently preventing one to 
screw the inter-process shared memory. Being different only 
because of scale -> not really different.

>>> Kernel mode code is the responsibility of the OS system, not 
>>> the app.
>>
>> In some (many?) large scale server systems OS is the app or at 
>> least heavily
>> integrated. Thinking about app as a single independent 
>> user-space process is a
>> bit.. outdated.
>
> Haha, I've used such a system (MSDOS) for many years. Switching 
> to process protection was a huge advance. Sad that we're 
> "modernizing" by reverting to such an awful programming 
> environment.

What is huge advance for user land applciation is a problem for 
server code. Have you ever heard "OS is the problem, not 
solution" slogan that is slowly becoming more popular in high 
load networking world?

>>>> It is all about system design.
>>>
>>> It's about the probability of coupling and the level of that 
>>> your system can
>>> stand. Process level protection is adequate for most things.
>>
>> Again, I am fine with advocating it as a resonable default. 
>> What frustrates me
>> is intentionally making any other design harder than it should 
>> be by explicitly
>> allowing normal cleanup to be skipped. This behaviour is easy 
>> to achieve by
>> installing custom assert handler (it could be generic Error 
>> handler too) but
>> impossible to bail out when it is the default one.
>
> Running normal cleanup code when the program is in an 
> undefined, possibly corrupted, state can impede proper shutdown.

Preventing cleanup can be done with roughly one line of code from 
user code. Enabling it back is effectively impossible. With this 
decision you don't trade safer default for more dangerous default 
- you trade configurable default for unavoidable.

To preserve same safe defaults you could define all thrown Errors 
to result in plain HLT / abort call with possibility to define 
user handler that actually throws. That would have addressed all 
concernc nicely while still not making life of those who want 
cleanup harder.

>> Because of abovementioned avoiding more corruption from 
>> cleanup does not sound
>> to me as strong enough benefit to force that on everyone.
>
> I have considerable experience with what programs can do when 
> continuing to run after a bug. This was on real mode DOS, which 
> infamously does not seg fault on errors.
>
> It's AWFUL. I've had quite enough of having to reboot the 
> operating system after every failure, and even then that often 
> wasn't enough because it might scramble the disk driver code so 
> it won't even boot.

I don't argue necessity to terminate the program. I argue strict 
relation "program == process" which is impractical and inflexible.

> It is my duty to explain how to use the features of the 
> language correctly, including how and why they work the way 
> they do. The how, why, and best practices are not part of a 
> language specification.

You can't just explain things to make them magically appropriate 
for user domain. I fully understand how you propose to design 
applications. Unfortunately, it is completely unacceptable in 
some cases and quite inconvenient in others. Right now your 
proposal is effectively "design applications like me or 
reimplement language / library routines yourself".

>>> NO CODE CAN BE RELIABLY EXECUTED PAST THIS POINT.
>> As I have already mentioned it almost never can be truly 
>> reliable.
>
> That's correct, but not a justification for making it less 
> reliable.

It is justification for making it more configurable.

> If D changes assert() to do unwinding, then D will become 
> unusable for building reliable systems until I add in yet 
> another form of assert() that does not.

My personal perfect design would be like this:

- Exceptions work as they do now
- Errors work the same way as exceptions but don't get caught by 
catch(Exception)
- assert does not throw Error but simply aborts the program 
(configurable with druntime callback)
- define "die" which is effectively "assert(false)"
- tests don't use assert

That would provide default behaviour similar to one we currently 
have (with all the good things) but leave much more configurable 
choices for system designer.

>> Some small chance of undefined behaviour vs 100% chance of 
>> resource leaks?
>
> If the operating system can't handle resource recovery for a 
> process terminating, it is an unusable operating system.

There are many unusable operating systems out there then :) And 
don't forget about remote network resources - while leak will 
eventually timeout there it will still have a negative impact.


More information about the Digitalmars-d mailing list