Discussion:
Exceptions in with_libc not working
Boris Mulder
2017-03-14 14:11:27 UTC
Permalink
Hi all,

Whenever I throw an exception somewhere in code inside a with_libc
lambda expression, and try to catch it outside of that block, it will
not catch that exception.

Example:

|t||ry {|

| Libc::with_libc([&] () { ... throw E||xception();
... } );|

|} catch (Exception &e) {||
Genode::log("caught");||||
}

|The "caught" will never be printed in this case. What can I do to
fix/work around this?
--
Met vriendelijke groet / kind regards,

Boris Mulder

Cyber Security Labs B.V. | Gooimeer 6-31 | 1411 DD Naarden | The Netherlands
+31 35 631 3253 (office)
Christian Helmuth
2017-03-14 15:01:22 UTC
Permalink
Hello Boris,
Post by Boris Mulder
Whenever I throw an exception somewhere in code inside a with_libc
lambda expression, and try to catch it outside of that block, it will
not catch that exception.
As I know the inner workings of the libc execution model this
observation sounds pretty natural, because in the end with_libc() is
just like: Please execute the given lambda body on an alternate stack.
The C++ exception implementation on the other hand heavily depends on
the current execution stack. Therefore, I wonder does it just not work
as expected or does it break gloriously?
Post by Boris Mulder
|t||ry {|
| Libc::with_libc([&] () { ... throw E||xception();
... } );|
|} catch (Exception &e) {||
Genode::log("caught");||||
}
|The "caught" will never be printed in this case. What can I do to
fix/work around this?
The only workaround I see at the moment is to move the exception
handling also into the lambda function. Reflection of error or
exceptional conditions to the enclosing function then could be
implemented by return values or state changes in referenced objects. I
admit that is not what one should expect from a C++ framework but to
be fair with_libc() just bridges a strange gap between Genode
components and the legacy C runtime world.

We also had a small discussion about a more advanced solution where
you may declare expected exception types that can be passed out of the
lambda like we did for RPC. But, a solution with reasonable effort
would also come with a bunch of limitations, e.g., that exception
types could only be POD-like.

Greets
--
Christian Helmuth
Genode Labs

https://www.genode-labs.com/ · https://genode.org/
https://twitter.com/GenodeLabs · /ˈdʒiː.nəʊd/

Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden
Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth
Boris Mulder
2017-03-21 09:37:25 UTC
Permalink
Well, what it does now it that the program just crashes with an
"uncaught exception".

Catching all exceptions inside becomes very hairy though, as functions
called inside with_libc might throw some exceptions that need to be
handled elsewhere.

For now the best fix seems to wrap only the necessary functions inside
with_libc (and have it return an error code the C way) and doing the
rest of the computations outside it.

Wouldn't it make sense to move with_libc into the critical functions
that need it themselves? Or to create wrappers for them in the include
files included by the components (socket.h etc.), similar to how posix
just transparently wraps main() in with_libc? This way the programmer is
not bothered with it at all unless it's necessary.
Post by Christian Helmuth
Hello Boris,
Post by Boris Mulder
Whenever I throw an exception somewhere in code inside a with_libc
lambda expression, and try to catch it outside of that block, it will
not catch that exception.
As I know the inner workings of the libc execution model this
observation sounds pretty natural, because in the end with_libc() is
just like: Please execute the given lambda body on an alternate stack.
The C++ exception implementation on the other hand heavily depends on
the current execution stack. Therefore, I wonder does it just not work
as expected or does it break gloriously?
Post by Boris Mulder
|t||ry {|
| Libc::with_libc([&] () { ... throw E||xception();
... } );|
|} catch (Exception &e) {||
Genode::log("caught");||||
}
|The "caught" will never be printed in this case. What can I do to
fix/work around this?
The only workaround I see at the moment is to move the exception
handling also into the lambda function. Reflection of error or
exceptional conditions to the enclosing function then could be
implemented by return values or state changes in referenced objects. I
admit that is not what one should expect from a C++ framework but to
be fair with_libc() just bridges a strange gap between Genode
components and the legacy C runtime world.
We also had a small discussion about a more advanced solution where
you may declare expected exception types that can be passed out of the
lambda like we did for RPC. But, a solution with reasonable effort
would also come with a bunch of limitations, e.g., that exception
types could only be POD-like.
Greets
--
Met vriendelijke groet / kind regards,

Boris Mulder

Cyber Security Labs B.V. | Gooimeer 6-31 | 1411 DD Naarden | The Netherlands
+31 35 631 3253 (office)
Norman Feske
2017-03-22 15:57:59 UTC
Permalink
Hi Boris,
Post by Boris Mulder
Wouldn't it make sense to move with_libc into the critical functions
that need it themselves? Or to create wrappers for them in the include
files included by the components (socket.h etc.), similar to how posix
just transparently wraps main() in with_libc? This way the programmer is
not bothered with it at all unless it's necessary.
I like this idea. We will certainly investigate it. Thank you for the
valuable feedback about the use of the 'with_libc' mechanism!

Cheers
Norman
--
Dr.-Ing. Norman Feske
Genode Labs

http://www.genode-labs.com · http://genode.org

Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden
Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth
Loading...