error, setjmp and exceptions

classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

error, setjmp and exceptions

Bilyk, Alex
I was wondering whether it's problematic to use 'error' function as an exception mechanism? The language shootout had an entry for this and, apparently, both Lua versions used 'error' function as a model for exceptions.  I have explored the mailing list archive and have some idea of what to expect. But if you are toying with the same idea why not discuss it.

1. Are there any common platforms that would have hard time with setjmp/longjmp C functions and thus with Lua error function in general. How about game consoles? PDAs?
2. Does calling 'error' impair garbage collection in any way? That is, if I had some user data referenced in a function that calls error would such user data be collected properly?
3. If you have used 'error' for exceptions, what are you impressions? What worked, what didn't?

Thanks,
AB


Reply | Threaded
Open this post in threaded view
|

Re: error, setjmp and exceptions

Roberto Ierusalimschy
> 1. Are there any common platforms that would have hard time with
> setjmp/longjmp C functions and thus with Lua error function in
> general. How about game consoles? PDAs?

Both seem like simple operations in a stack architecture. But almost
any operation can be too slow in a specific machine.


> 2. Does calling 'error' impair garbage collection in any way? That is,
> if I had some user data referenced in a function that calls error would
> such user data be collected properly?

No and yes.


> 3. If you have used 'error' for exceptions, what are you
> impressions? What worked, what didn't?

One problem is that you must differentiate between exceptions and
"real" errors. Another is that the "try" clause must be a function
call. You can (should?) use anonymous functions for that, but then each
"try" creates a new function. This is not too bad, but it causes some
overhead. It is cheaper to use a fixed function for that, but the code
may not look so clean.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

Bilyk, Alex
In reply to this post by Bilyk, Alex

-----Original Message-----
From: Roberto Ierusalimschy [[hidden email]]
Sent: Thursday, December 18, 2003 10:53 AM
To: Lua list
Subject: Re: error, setjmp and exceptions 


> 2. Does calling 'error' impair garbage collection in any way? That is,
> if I had some user data referenced in a function that calls error would
> such user data be collected properly?

No and yes.
Could you elaborate on this? I am not concerned about performance at this point. Rather, I am thinking of platform compatibility and Lua VM integrity. If there were cases when calling 'error' (as a matter of exception) would leave Lua VM is a state unsuitable for further execution I would like to know about them. Not having proper GC in such cases would also be my concern.
I am exploring this for unrolling Lua call stack to a given level. But after it happens I intend to proceed with executing other Lua code as if the unrolling had never happened.
Alex

Reply | Threaded
Open this post in threaded view
|

Re: error, setjmp and exceptions

Roberto Ierusalimschy
>> Does calling 'error' impair garbage collection in any way?

> No


>> if I had some user data referenced in a function that calls error would
>> such user data be collected properly?

> [and] yes.

'error' does not impair the VM at all (unless it is called in
unprotected mode, yielding to a panic exit). It unwinds the stack,
leaving everything in perfect conditions to proceed executing. You can
call as many "errors" as you want, whenever you want (even from inside C
code), and you should not be able to achieve an unconsistent state.
(Again, the exception being if you call error in unprotected mode,
that is, outside any call to pcall or lua_pcall.)

-- Roberto

Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

Kevin Baca-2
In reply to this post by Bilyk, Alex
This may be common knowledge, but I thought I'd mention it.

Calling lua_error() from a C/C++ function can result in leaked
resources.  This can be more subtle in C++ than in C.

int func( lua_State* L )
{
    std::vector< int > v;

    v.push_back( 1 );

    lua_pushstring( L, "Leaked some memory" );
    lua_error( L );

    return 0;
}

The vector's destructor never gets called and its memory is leaked.

-Kevin

> I was wondering whether it's problematic to use 'error' 
> function as an exception mechanism? The language shootout had 
> an entry for this and, apparently, both Lua versions used 
> 'error' function as a model for exceptions.  I have explored 
> the mailing list archive and have some idea of what to 
> expect. But if you are toying with the same idea why not discuss it.
> 
> 1. Are there any common platforms that would have hard time 
> with setjmp/longjmp C functions and thus with Lua error 
> function in general. How about game consoles? PDAs? 2. Does 
> calling 'error' impair garbage collection in any way? That 
> is, if I had some user data referenced in a function that 
> calls error would such user data be collected properly? 3. If 
> you have used 'error' for exceptions, what are you 
> impressions? What worked, what didn't?
> 
> Thanks,
> AB
> 


Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

Joshua Jensen
> This may be common knowledge, but I thought I'd mention it.
> 
> Calling lua_error() from a C/C++ function can result in 
> leaked resources.  This can be more subtle in C++ than in C.
> 
> int func( lua_State* L )
> {
>     std::vector< int > v;
>     ...
>     lua_error( L );
>     return 0;
> }
> 
> The vector's destructor never gets called and its memory is leaked.

I've run into this SO many times.  I'm not sure if it is doable, but perhaps
lua_error() should set a flag for the error condition and only fire when the
Lua VM is back in control?

Josh


Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

RLak-2
In reply to this post by Bilyk, Alex
> I am not concerned about performance at this point. Rather, I am 
thinking of platform compatibility and Lua VM integrity. If there were 
cases when calling 'error' (as a matter of exception) would leave Lua VM 
is a state unsuitable for further execution I would like to know about 
them. Not having proper GC in such cases would also be my concern.

> I am exploring this for unrolling Lua call stack to a given level. But 
after it happens I intend to proceed with executing other Lua code as if 
the unrolling had never happened.

This mechanism has worked just fine for me. I cannot see any reason why it 
would cause problems -- I looked through the VM code carefully before I 
deployed it.

As far as I know, setjmp and longjmp are required by ANSI C. This doesn't 
mean they are implemented perfectly on every architecture, but since they 
are used by so many big packages, it seems unlikely that they wouldn't 
work in the case of Lua.

This style of programming is precisely the reason I prefer automatic 
garbage collection -- Lua will not leak memory, I am sure, but you should 
watch out for any C libraries that you longjmp through on callbacks.

R.

Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

Bilyk, Alex
In reply to this post by Bilyk, Alex

>-----Original Message-----


>From: Joshua Jensen [[hidden email]]
>Sent: Thursday, December 18, 2003 11:28 AM
>To: 'Lua list'
>Subject: RE: error, setjmp and exceptions
>
>
>> This may be common knowledge, but I thought I'd mention it.
>>
>> Calling lua_error() from a C/C++ function can result in
>> leaked resources.  This can be more subtle in C++ than in C.
>>
>> int func( lua_State* L )
>> {
>>     std::vector< int > v;
>>     ...
>>     lua_error( L );
>>     return 0;
>> }
>>
>> The vector's destructor never gets called and its memory is leaked.
>
>I've run into this SO many times.  I'm not sure if it is
>doable, but perhaps
>lua_error() should set a flag for the error condition and only
>fire when the
>Lua VM is back in control?

 

But there is no guaranty the C function calling an lua_error is the only one that needs cleaning. So, I don't think the flag is quite a solution to abandoned resources on C stack. It would be much easier to say istead

int func( lua_State* L )

{
    {
        std::vector< int > v;
        ...
    }


    lua_error( L );
    return 0;
}

but then, as you pointed out, one is prone to not having done so and would not clean any other C functions anyway. I wonder if one could use a C++ exception instead of lua_error to accomplish similar thing. 

Alex

Reply | Threaded
Open this post in threaded view
|

Re: error, setjmp and exceptions

Roberto Ierusalimschy
In reply to this post by Joshua Jensen
> The vector's destructor never gets called and its memory is leaked.

If you compile Lua as C++ code, it is not difficult to change it
to use real exceptions instead of setjmp/longjmp. Lua 5.1 will have
a compilation flag for that. I hope the next lines give the
general idea:

>  #ifndef LUA_USEEXCEPTIONS
>
>  #define L_THROW(c)      longjmp((c)->b, 1)
>  #define L_TRY(c,a)      if (setjmp((c)->b) == 0) { a }
>
>  #else
>
>  #define L_THROW(c)      throw(c)
>  #define L_TRY(c,a)      try { a } catch(...) \
>                                  { if ((c)->status == 0) (c)->status = -1; }
>
>  #endif

This is not a perfect solution (other C++ exceptions are also catched
by Lua protected calls), but it seems to work ok.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re[2]: error, setjmp and exceptions

Gunnar Zötl
In reply to this post by Roberto Ierusalimschy
Hello there,

on a related note, are there any plans to support exeption handling in
future versions of lua? try-catch would be nice, try-catch-finally
would be just great :-)

Gunnar



Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

Kevin Baca-2
In reply to this post by Bilyk, Alex
I saw an earlier post along with a patch where the poster replaced the
setjmp()/longjmp() idiom with C++ exceptions.

It worked for him, but there are size and performance penalties with C++
exceptions.  The only alternative (that I know) is to take extra care
with your C++ code.

I have a patch and a set of macros that allow you to do something like
this:

luaL_try( L )
{
    //protected code
}
luaL_catch( 2 )
{
    //handle exception
}
luaL_tryend;

This opens a new can of worms.  Anything declared outside the try block
and used inside the try block must be declared volatile.  This is
typical of the the setjmp()/longjmp() exception idiom.

I eventually opted for not using this method.

-Kevin

-----Original Message-----
From: [hidden email]
[[hidden email]] On Behalf Of Bilyk, Alex
Sent: Thursday, December 18, 2003 11:40 AM
To: Lua list
Subject: RE: error, setjmp and exceptions


>-----Original Message-----
>From: Joshua Jensen [[hidden email]]
>Sent: Thursday, December 18, 2003 11:28 AM
>To: 'Lua list'
>Subject: RE: error, setjmp and exceptions
>
>
>> This may be common knowledge, but I thought I'd mention it.
>>
>> Calling lua_error() from a C/C++ function can result in
>> leaked resources.  This can be more subtle in C++ than in C.
>>
>> int func( lua_State* L )
>> {
>>     std::vector< int > v;
>>     ...
>>     lua_error( L );
>>     return 0;
>> }
>>
>> The vector's destructor never gets called and its memory is leaked.
>
>I've run into this SO many times.  I'm not sure if it is
>doable, but perhaps
>lua_error() should set a flag for the error condition and only
>fire when the
>Lua VM is back in control?

But there is no guaranty the C function calling an lua_error is the only
one that needs cleaning. So, I don't think the flag is quite a solution
to abandoned resources on C stack. It would be much easier to say istead
int func( lua_State* L )
{
    {
        std::vector< int > v;
        ...
    }

    lua_error( L );
    return 0;
}

but then, as you pointed out, one is prone to not having done so and
would not clean any other C functions anyway. I wonder if one could use
a C++ exception instead of lua_error to accomplish similar thing. 

Alex


Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

Virgil Smith
In reply to this post by Bilyk, Alex
As a relevant sampling point (especially since C++ exceptions have been
mentioned), in my work we do lots of embedded programming, PC programming,
and Windows CE programming.  In all of that (using probably a sampling of
~5-8 embedded C compilers) we have never seen setjmp/longjmp NOT be
implemented by the compiler vendor.  However, Windows CE (and the associated
Embedded Visual Tools) does not support C++ exceptions (and C++ compilers
for embedded uCs/platforms are still fairly rare even though they are
starting to catch on).

-----Original Message-----
From: [hidden email]
[[hidden email] Behalf Of Bilyk, Alex
Sent: Thursday, December 18, 2003 12:10 PM
To: Lua list
Subject: error, setjmp and exceptions


I was wondering whether it's problematic to use 'error' function as an
exception mechanism? The language shootout had an entry for this and,
apparently, both Lua versions used 'error' function as a model for
exceptions.  I have explored the mailing list archive and have some idea of
what to expect. But if you are toying with the same idea why not discuss it.

1. Are there any common platforms that would have hard time with
setjmp/longjmp C functions and thus with Lua error function in general. How
about game consoles? PDAs?
2. Does calling 'error' impair garbage collection in any way? That is, if I
had some user data referenced in a function that calls error would such user
data be collected properly?
3. If you have used 'error' for exceptions, what are you impressions? What
worked, what didn't?

Thanks,
AB

<<attachment: winmail.dat>>

Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

RLak-2
In reply to this post by Bilyk, Alex
> It worked for him, but there are size and performance penalties with C++
> exceptions.  The only alternative (that I know) is to take extra care
> with your C++ code.

That depends a lot on your C++ compiler; it is not always drastic.

The other alternative (if you have access to the source code for your
C++ libraries) is to use the Boehm&al conservative garbage collector
and not worry about freeing. (See this thread on gclist for issues
with STL: http://lists.tunes.org/archives/gclist/2003-May/002460.html)





Reply | Threaded
Open this post in threaded view
|

Off Topic Correction

John Paquin
In reply to this post by Virgil Smith
>> Windows CE (and the associated Embedded Visual Tools) does not support
C++ exceptions

This is changing.  Windows CE 3.0 and Ebedded Visual Tools 4.0 now support
C++ exceptions (and the STL)

-----Original Message-----
From: [hidden email]
[[hidden email]]
Sent: Thursday, December 18, 2003 3:28 PM
To: 'Lua list'
Subject: RE: error, setjmp and exceptions

As a relevant sampling point (especially since C++ exceptions have been
mentioned), in my work we do lots of embedded programming, PC programming,
and Windows CE programming.  In all of that (using probably a sampling of
~5-8 embedded C compilers) we have never seen setjmp/longjmp NOT be
implemented by the compiler vendor.  However, Windows CE (and the associated
Embedded Visual Tools) does not support C++ exceptions (and C++ compilers
for embedded uCs/platforms are still fairly rare even though they are
starting to catch on).

-----Original Message-----
From: [hidden email]
[[hidden email] Behalf Of Bilyk, Alex
Sent: Thursday, December 18, 2003 12:10 PM
To: Lua list
Subject: error, setjmp and exceptions


I was wondering whether it's problematic to use 'error' function as an
exception mechanism? The language shootout had an entry for this and,
apparently, both Lua versions used 'error' function as a model for
exceptions.  I have explored the mailing list archive and have some idea of
what to expect. But if you are toying with the same idea why not discuss it.

1. Are there any common platforms that would have hard time with
setjmp/longjmp C functions and thus with Lua error function in general. How
about game consoles? PDAs?
2. Does calling 'error' impair garbage collection in any way? That is, if I
had some user data referenced in a function that calls error would such user
data be collected properly?
3. If you have used 'error' for exceptions, what are you impressions? What
worked, what didn't?

Thanks,
AB

<<attachment: winmail.dat>>

Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

Bilyk, Alex
In reply to this post by Bilyk, Alex
Thank you for the input, folks:)

Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

marcus.cf
In reply to this post by Bilyk, Alex
I wonder how Lua manages dynamic allocation and longjmp 
internally...
I've found out that Lua uses a neat jmb_buf linked list 
to handle multiple jump destinations, but I don't know 
what it does to avoid leaking memory.

 
__________________________________________________________________________
Acabe com aquelas janelinhas que pulam na sua tela.
AntiPop-up UOL - É grátis!
http://antipopup.uol.com.br/



Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

Bilyk, Alex
In reply to this post by Bilyk, Alex
I think the only dynamic allocations Lua makes are those for Lua objects, which end up being stored somewhere in Lua state. So, in general, there is nothing that would be sitting on C stack in need for deallocation or a cleanup.

Alex.

>-----Original Message-----
>From: marcus.cf [[hidden email]]
>Sent: Friday, December 19, 2003 11:05 AM
>To: [hidden email]
>Subject: RE: error, setjmp and exceptions
>
>
>I wonder how Lua manages dynamic allocation and longjmp 
>internally...
>I've found out that Lua uses a neat jmb_buf linked list 
>to handle multiple jump destinations, but I don't know 
>what it does to avoid leaking memory.
>
> 
>_______________________________________________________________
>___________
>Acabe com aquelas janelinhas que pulam na sua tela.
>AntiPop-up UOL - É grátis!
>http://antipopup.uol.com.br/
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

RE: error, setjmp and exceptions

RLak-2
In reply to this post by Bilyk, Alex
> I've found out that Lua uses a neat jmb_buf linked list 
> to handle multiple jump destinations, but I don't know 
> what it does to avoid leaking memory.

It uses garbage collection :)

After the longjmp, it pops the stack back to where it was.
The next garbage collection, if there is no accessible
pointer to an object, the object is gone. Simple and
effective. 

Reply | Threaded
Open this post in threaded view
|

Re: error, setjmp and exceptions

Mark Hamburg-4
In reply to this post by Roberto Ierusalimschy
Throwing the Lua state is a little interesting as a choice but I guess it
doesn't cause any problems.

Please make it possible to separately define L_THROW and L_TRY as well
though I suspect that in order to do exception translation I will probably
still end up overriding luaD_throw and luaD_rawrunprotected.

Thanks.
Mark

on 12/18/03 11:57 AM, Roberto Ierusalimschy at [hidden email] wrote:

>> The vector's destructor never gets called and its memory is leaked.
> 
> If you compile Lua as C++ code, it is not difficult to change it
> to use real exceptions instead of setjmp/longjmp. Lua 5.1 will have
> a compilation flag for that. I hope the next lines give the
> general idea:
> 
>>  #ifndef LUA_USEEXCEPTIONS
>> 
>>  #define L_THROW(c)      longjmp((c)->b, 1)
>>  #define L_TRY(c,a)      if (setjmp((c)->b) == 0) { a }
>> 
>>  #else
>> 
>>  #define L_THROW(c)      throw(c)
>>  #define L_TRY(c,a)      try { a } catch(...) \
>>                                  { if ((c)->status == 0) (c)->status = -1; }
>> 
>>  #endif
> 
> This is not a perfect solution (other C++ exceptions are also catched
> by Lua protected calls), but it seems to work ok.
> 
> -- Roberto
>