On Thu, May 24, 2012 at 9:16 PM, David Rajchenbach-Teller
<[email protected]> wrote:
> On 5/24/12 12:40 PM, Bennie Kloosteman wrote:
>>> * The system _must_ not prevent developers from calling C code from Rust.
>>> * The system _must_ not prevent developers from passing a pointer to a
>>> Rust function to C code that will call back to it.
>>> * The system _must_ not prevent, some day, developers from calling Rust
>>> from JavaScript.
>>> * The system _must_ not prevent, some day, developers from calling
>>> JavaScript from Rust.
>>
>> These should be unsafe - I believe this is the case with rust.
>
> I am not sure if you mean this in relation with all four points or with
> the last one. So, indeed, I see no reason to change the fact that calls
> to C are considered unsafe.
>
> For calls to JavaScript, I have not given it much thought. I suppose
> that they could be either unsafe or somehow managed.

externals calls either must work 100% ( including type conversions) or
be marked unsafe... if it breaks type or memory safety you need to say
that.

Speaking of which we can handle C errors in calls but what about C++
exceptions ? Does any C++ code we hook need exception wrappers ?
Also any error system rust should work when called from C  ( unlike
C++ exceptions) .


>
>>> * Issues _must_ not be restricted to integers (or to one single type).
>>
>> Yes  but returning error codes and then looking up further issue
>> detail separately is quite useful since your passing around little
>> information it gives the highest chance in a partially unsafe
>> environment of working out what happened . eg if the stack is
>> corrupted or you have major issues its useful that the error is memory
>> logged  ( eg in ring 0 in a  rust based kernel ) and then retrieved .
>> A simple  integer return value has a much better chance..
>
> Interesting point.
> Are we talking about implementing Servo with a ring-like mechanism?
>
> If so, I suspect that we may simply not want this kind of issues to
> cross ring boundaries. Otherwise, if we let high-level issues cross
> boundaries, we could be sending closures, for instance, which sounds
> like a bad idea.
>
> For the moment, I believe that we should assume that the issue mechanism
> will not be used for crossing ring boundaries.

Is rust or this error handling solely for Servo ? What about writing
say a kernel or Linux kernel modules in rust ? To me system
programming is where Rust should be. If its all working that's fine
but  I was showing some horrible worst cases and its still nice to get
some error information rather than a horrible crash .

A similar thing can occur with any external call to C or asm. But the
concept is the same try to get at least an error code returned even if
the most abysmal circumstances.

>
>> This could be a 64 bit  value with the low 32 bits the error and the
>> upper 32 bit some sort of hash code.
>>
>> A more detailed but not guaranteed representation should be a detailed
>> structure. with time stamps etc  I would even say this detail should
>> be created asynchronously via a new task while the actual error is
>> returned immediately .
>>
>> errno is a pain ,  but not because it returns an int but because all
>> the information you can retrieve on it is a error string.
>>
>> Actually you could log all the detail and just reference an index to
>> the log , Though this would require recent log entries to be
>> recallable and have more detail in the log fields eg error category
>> and level  ( which are useful in a log anyway)
>
> All these are interesting points, although perhaps they arrive a little
> too early in the thread :)
>

Im not so young anymore so when I train of thoughts I like to get it
on E-paper ;-)

>>> * The default behavior in case of untreated issue _should_ be to
>>> gracefully kill the task or the application.
>>
>> If its integrated with tracing and logging the default behaviour
>> depends on the error type
>>
>> eg Trace  , Log, Warning or Error continue , Critical  = halt.
>
> A tracer/logger with this kind of semantics could certainly be built on
> top of the issue mechanism. I tend to believe that that they should be
> integrated from the start, though.

Agree,
>
>>> * Whenever an untreated issue kills a task/application, it _should_
>>> produces a report usable by the developer for fixing the issue.
>>> * It _should_ be possible to deactivate that killing behavior. There
>>> _may_ be limitations.
>>> * It _should_ be possible to deactivate that killing behavior
>>> conditionally (i.e. only for some errors).
>>
>> also a task can monitor child tasks for errors ( I don't think Rust
>> has events but something like that) and choose on error to abort or
>> continue depending on the error condition. .
>
> Sounds interesting. I suspect (but I am not sure) that this is something
> that could/should be built on top of a more elementary issue mechanism.
> Could you provide a scenario that we could use as a working base?


Yes it probably should be built on top ..but I really like the model
where items received from a pipe/channel are broken out and fired as
events ( which multiple callers can hook).

Note an interesting issue here , if the task  is in a bad error state
it  possibly may not use the "pipe/channel" for communication to the
parent .. How is this handled ? SIgnals ?

>
>
>>> * The system _should_ eventually have a low runtime cost – in
>>> particular, the case in which no killing happens should be very fast.
>>
>> I don't think the performance of an error system is important at all ,
>> its more important to have stack and meta data to resolve the issue
>> especially in debug builds ( and meta data is very slow) .  This leads
>> to people using errors to pass/check  state which is a bad habit
>
> Could you elaborate on that last sentence?

int I = 0;
try{
   i = Int32.Parse( string)
}
catch (Exception ex)
{
 // handle cant convert
}


vs

int I  = 0 ;
if ( Int32.TryParse ( &I , string)
    {  // handle cant convert }


>
> I am starting to believe that collecting [meta]data might be something
> that we want to configure on a usage basis. For instance, in function
> |move|, introduced a few e-mails ago (I just reposted it at
> https://gist.github.com/2781413 for convenience), we may be interested
> in the metadata of calls to lines 10 and 12, but gathering metadata for
> the calls in lines 2 and 6 is generally a waste of resources.

Yes it should be optional eg you don't always want it on traces and
logs , most of the time on errors ( always on debug) and always on
critical errors.

>
> If we think of this as exceptions, it could be that we want several the
> ability to specify if/when we want to gather metadata at the level of an
> equivalent of |try|. I believe that this fits nicely with what Graydon
> had in mind, by the way.
>
>> I would add
>> * Tasks are the error scope / unit
>>
>> * should we have an exception like syntax that automatically creates a
>> sub task for the embedded statements ( and hence means those
>> statements cannot result in failure of the parent tasks) . Since
>> errors are scoped to the task , the easy way is a new task .
>
> This looks quite heavyweight to me. So, if you don't care about
> performance, sure. But I'm clinging to the hope that we can make
> something faster, so I disagree for the moment :)

It is heavy weight but most Rust errors will not have exception
scopes... just functions that return an errorno or pointerto an Error
object ,  The concept of exception scope is useful though eg a single
threaded message pump is normally

foreach ( var message in buffer)
{
 try {
       ProcessMessage( message);
}
catch (ThreadAbortException ex) { // handle }
catch (Exception ex) { // handle and continue to next message }
}

We want every possible error handled so the loop never stops  ..no
matter what happens . eg an out of bounds array , null pointer or core
dump in an external call  should kill the message but not the message
pump.  Obviously the unsafe / external core dump is difficult and may
not be possible but it is desirable.

So these are a counterpoint to fail , we could say failscope and fail .



>> * It should be integrated with tracing and logging.
>
> Looks like two distinct things to me. Why couldn't you build a tracing +
> logging tool on top of it?

Above you say it should be integrated … Yes it can be built in the
standard libs but It should still be integrated  and more importantly
the logging and tracing considered  in the design not in isolation ,
look how hard it is in C  , in theory every time you return a null or
non zero return code you should be logging / tracing .

ie  ptr = malloc(N);
if ( ptr == NULL)
{
   //get  error no
   // log / trace
   // return to user
}

Why does the caller need to do the logging  ? You may have 1000s of
calls  so you need to make wrappers just for the logging . malloc
should do it ( depending on app configuration) especially when logging
is built into the language.  Since the standard lib doesn't  the
caller has to do it … The best place to log errors is the one that
generated the error and by integrating the error system with logging
it can be done automatically.


I have written a ton of code over the years  ( when I bother in
quality programs) like catch (exception)   { if blah blah / log  /
trace ; if severity is  < n rethrow } and the c style error code way
is abysmal here  if you want to log . Yet 99% of the time all you want
is some sort of log everything if the severity is > N  in a config
file concept without writing the code.

Maybe something like :

1. Fail  returns a ref to  Error type it creates
2. Stdlib Errors Return a ref to Error type  ( which can be the
Error.Success   so you can go if ( function() != Error.Success)
3. When error type is created , error type has a hook for logging /
tracing on construction. by default this should log depending on a
configurable level.
4. Most errors should be statically defined and allow strongly typed checking

BTW this is an interesting article it covers .NET /C++ Exceptions vs
ErrorCodes vs COM HRESULT / IErrorInfo at the end

http://blogs.msdn.com/b/cbrumme/archive/2003/10/01/51524.aspx


Ben
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to