rust-lua53 icon indicating copy to clipboard operation
rust-lua53 copied to clipboard

How safe is State::error?

Open jugglerchris opened this issue 9 years ago • 5 comments

Hi, I'm trying to work out how safe calling the error method is, for reporting problems back to Lua code. It causes longjmp to unwind past a Rust function, which sounds undefined, but can it be safe if I'm careful?

I'd be interested in both "in practice ok" and "yes it's correct" type answers.

Thanks,

Chris

jugglerchris avatar Mar 19 '16 11:03 jugglerchris

From the reference:

12.3 Behavior considered undefined

Unwinding into Rust from foreign code or unwinding from Rust into foreign code. Rust's failure
system is not compatible with exception handling in other languages. Unwinding must be caught
and handled at FFI boundaries.

All bets are off if you raise a Lua error outside of a pcall. I think to properly handle this, LUAI_TRY and LUAI_THROW need to be redefined to call into the appropriate Rust functions to perform setup/teardown.

jcmoyer avatar Apr 03 '16 21:04 jcmoyer

Hi, Thanks for the response, which I think confirms what I thought, which is that I'm ok with errors from Lua code if I always use pcall, but there isn't a safe way to generate a Lua error from Rust code.

When thinking about what I could do about this, I thought it would be nice if the Rust function could be written like:

fn myFunction(state: &mut lua::State) -> Result<c_int, String> {
   ...stuff with try!() etc.
}

where an Err result could be translated into a lua_error lower down.

So it would go something like:

  1. Lua calls foo()

  2. foo, which could be Lua or C, is a wrapper which is the inverse of pcall, something like:

    ok, results = wrap_foo() -- wrap_foo is probably an upvalue to a generic C/Lua function.
    if ok then
       return results
    else
       error(results) -- error message
    end
    
  3. wrap_foo is an optional wrapper, now Rust, which calls real_foo, and returns true, results or false, error msg depending on the Result returned.

With those layers in place, I could then write reasonably natural Rust functions and have errors translated automatically.

I think I've got all I need to implement this on top of rust-lua53 without any changes your end, though it would be convenient (and I guess a little faster) if the library supported calling error safely directly from Rust; however that looks hard to me.

I'd be interested in any comments/suggestions/obvious problems with my mad scheme above, but I'm happy to close this issue now; but I'll leave that to you in case you want to implement anything.

jugglerchris avatar Apr 03 '16 22:04 jugglerchris

I've been working on some things quite similar to this here (see components/script/environment.rs). I've added a few convenience wrappers around lua::State, including ones that allow closures to be pushed onto the stack and functions with the signature:

fn my_function(environment: Environment) -> Result<i32, Box<Error>> {
    // ...
    Ok(1)
}

@jugglerchris Perhaps you'd be interested in collaborating on a higher-level Rust-Lua library? I've got some neat ideas that don't really fit into this project (from my understanding, this is meant to be a 1:1 Rust binding to Lua).

sagebind avatar May 30 '16 15:05 sagebind

@coderstephen I was planning on (eventually) splitting out what I have into a separate crate; I'd be happy to work together. I've implemented the scheme in my above comment and a way to safely share Rust types in what I think is a (dynamically) type-safe way with Lua. I'll try to prioritise getting that up somewhere, hopefully sometime this week.

jugglerchris avatar May 31 '16 09:05 jugglerchris

I've split out my in-development (badly documented, inconsistently named and so on) interface into a github repo: https://github.com/jugglerchris/rlua in case it's of interest. See the _push_closure method which takes a Rust function returning a Result, and wraps it via a small Lua stub which converts an Err into a call to the Lua error function. Similarly run_loaded_lua converts Lua errors back into a Rust Err.

It's all a bit messy and rough at the moment, but I'm happy for that to be a starting point for a more generally useful and Rustic (is that the word?) interface on top of this one.

jugglerchris avatar May 31 '16 23:05 jugglerchris