emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Dynamic loading progress


From: Daniel Colascione
Subject: Re: Dynamic loading progress
Date: Sun, 13 Sep 2015 21:37:24 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0

On 09/13/2015 09:18 PM, Stefan Monnier wrote:
>> It'll be hard enough to get developers to properly unwind their own
>> code, especially because we're only talking about a case that's active
>> when things go wrong. Of course we can make non-local control flow
>> work: it works well enough inside Emacs.
> 
> You lost me.
> 
>> I'm objecting to this approach because it's a bug machine, especially
> 
> What is "this approach"?

Specifically, I don't think Emacs public module API functions should
ever return non-locally. "This approach" means longjmping out to
condition-case instead of returning normally from Emacs module API
functions.

> 
>> without the Emacs Lisp and GC machinery.
> 
> AFAIK we do have the Elisp and the GC machinery available.

Yes, but the whole point of the module system is to access non-Emacs
libraries, and these libraries will have its own resource tracking
systems, which won't integrate with the Emacs GC core.

Longjmp in the Emacs core is convenient: if you want to make an Emacs
Lisp string, you can call make_string, and even if the next line of the
program longjmps, the GC will take care of releasing the resources
associated with that string.

Imagine if you had to individually arrange to call free on both the
success and error paths for every string you wanted to allocate ---
that's what life will will be like for module authors. I don't imagine
most modules will be using Emacs GCed resources for their own data, so
they'll have to arrange for cleanups manually.

>> It breaks C++ RAII, because there's no way the longjmp out of Emacs
>> can run C++ destructors.
> 
> This seems to refer to the "point 5" above.  As mentioned it's easy to
> prevent the longjmp from escaping back into the surrounding non-Emacs
> (e.g. C++) code.

I agree that it's possible. I don't agree that it's easy.

If the interface is like internal_condition_case, developers will have
to define another C-level function to act as an longjmp barrier, and
they'll have to do that for every call from their module to the Emacs
core. That's a lot of boilerplate. I'm afraid that developers will skip
this boilerplate and just make Emacs API calls directly, leading to the
presence of latent bugs that are hard to diagnose and fix. This sloppy
approach will appear to work fine, but things can go very wrong in rare
circumstances.

The problems I foresee are of the form "Emacs crashes when I hit C-g
with just the right timing", or "Emacs leaks memory if find-file fails
while this module calls it".  You can imagine Emacs deadlocking if a
module takes a long, Emacs longjmps past that lock's release, and then
later (perhaps much later) we try to take that lock and never acquire it.

Sure, it's possible to introduce similar bugs by not checking error
codes or some global error flag. The difference is that the danger is
better-understood (since many more C programs use error codes or error
flags than use longjmp), and we can diagnose the problems arising from a
failed error check more reliably than we can diagnose the problems that
can arise from a failed stack cleanup.

For example, if we use a global error flag, and we see an Emacs module
API function called with this error flag set, we can abort immediately,
pinpointing the problem. Or we can fail the call, warn the user, or do
anything else sensible. We can't even _detect_ the kind of damage
produced by missing stack cleanups.

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]