* Dynamic modules: emacs-module.c and signaling errors
@ 2015-11-24 19:41 Eli Zaretskii
2015-11-24 19:45 ` Eli Zaretskii
` (2 more replies)
0 siblings, 3 replies; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-24 19:41 UTC (permalink / raw
To: Philipp Stephani, aurelien.aptel+emacs, tzz, dancol; +Cc: emacs-devel
In "emacs -Q", load the modules/mod-test/mod-test module, then try
this:
M-: (mod-test-sum "1" 2) RET
Result: Emacs aborts. This happens because the eassert in
module_extract_integer aborts, when that function is called for the
2nd time:
static intmax_t
module_extract_integer (emacs_env *env, emacs_value n)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
Lisp_Object l = value_to_lisp (n);
if (! INTEGERP (l))
{
module_wrong_type (env, Qintegerp, l);
return 0;
}
The first call to module_extract_integer correctly detects the wrong
type of argument and calls module_wrong_type. But module_wrong_type
just records the problem in the env structure, it doesn't signal any
Lisp error, like an Emacs primitive would. So the actual error goes
undetected, and is masked by the assertion violation (because Emacs is
built with --enable-checking).
Since this obviously works as it was designed, my question is: how
should a module be written so that this kind of errors signal a normal
Lisp error we are accustomed with Emacs primitives?
TIA
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 19:41 Dynamic modules: emacs-module.c and signaling errors Eli Zaretskii
@ 2015-11-24 19:45 ` Eli Zaretskii
2015-11-24 20:12 ` Tom Tromey
2015-11-25 18:09 ` Philipp Stephani
2 siblings, 0 replies; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-24 19:45 UTC (permalink / raw
To: p.stephani2; +Cc: aurelien.aptel+emacs, tzz, dancol, emacs-devel
> Date: Tue, 24 Nov 2015 21:41:12 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: emacs-devel@gnu.org
>
> The first call to module_extract_integer correctly detects the wrong
> type of argument and calls module_wrong_type. But module_wrong_type
> just records the problem in the env structure, it doesn't signal any
> Lisp error, like an Emacs primitive would. So the actual error goes
> undetected, and is masked by the assertion violation (because Emacs is
^^^^^^^^^^
I meant to say "unreported", of course.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 19:41 Dynamic modules: emacs-module.c and signaling errors Eli Zaretskii
2015-11-24 19:45 ` Eli Zaretskii
@ 2015-11-24 20:12 ` Tom Tromey
2015-11-24 20:49 ` Eli Zaretskii
2015-11-25 18:09 ` Philipp Stephani
2 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2015-11-24 20:12 UTC (permalink / raw
To: Eli Zaretskii
Cc: aurelien.aptel+emacs, Philipp Stephani, dancol, tzz, emacs-devel
>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
Eli> Since this obviously works as it was designed, my question is: how
Eli> should a module be written so that this kind of errors signal a normal
Eli> Lisp error we are accustomed with Emacs primitives?
What I did in my module is do an error check after every call in to
Emacs, returning early when one is seen. Then eventually control
returns to Fmodule_call, which handles translating this to a Lisp
signal.
The module in question isn't doing this check after calling
extract_integer, but it should.
Tom
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 20:12 ` Tom Tromey
@ 2015-11-24 20:49 ` Eli Zaretskii
2015-11-24 21:34 ` Paul Eggert
0 siblings, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-24 20:49 UTC (permalink / raw
To: Tom Tromey; +Cc: aurelien.aptel+emacs, p.stephani2, dancol, tzz, emacs-devel
> From: Tom Tromey <tom@tromey.com>
> Cc: Philipp Stephani <p.stephani2@gmail.com>, aurelien.aptel+emacs@gmail.com, tzz@lifelogs.com, dancol@dancol.org, emacs-devel@gnu.org
> Date: Tue, 24 Nov 2015 13:12:30 -0700
>
> What I did in my module is do an error check after every call in to
> Emacs, returning early when one is seen. Then eventually control
> returns to Fmodule_call, which handles translating this to a Lisp
> signal.
Thanks. However, this is highly non-obvious, and IMO quite error
prone. The consequences of failing to conform to this paradigm are
dire: the error goes unreported, and instead an unrelated assertion
blows up.
Perhaps we should remove these assertions, or at least make them
conditional on something that isn't ENABLE_CHECKING, since it seems
they were added for debugging emacs-module.c, not for catching errors
in modules.
Btw, using this method the module code becomes very tedious, something
like
intmax_t a = env->extract_integer (env, args[0]);
if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
return NULL;
intmax_t b = env->extract_integer (env, args[1]);
if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
return NULL;
etc.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 20:49 ` Eli Zaretskii
@ 2015-11-24 21:34 ` Paul Eggert
2015-11-24 21:55 ` Daniel Colascione
2015-11-24 22:21 ` Tom Tromey
0 siblings, 2 replies; 59+ messages in thread
From: Paul Eggert @ 2015-11-24 21:34 UTC (permalink / raw
To: Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, dancol, tzz, emacs-devel
On 11/24/2015 12:49 PM, Eli Zaretskii wrote:
> Btw, using this method the module code becomes very tedious
It's so tedious I can't imagine using it that way. Module authors
shouldn't have to call env->non_local_exit_check (env) after every
function call, to see whether the function actually worked. Functions
should be able to signal an error, just as they can in the Emacs core,
and the error should propagate through calls in a natural way.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 21:34 ` Paul Eggert
@ 2015-11-24 21:55 ` Daniel Colascione
2015-11-25 6:52 ` Paul Eggert
2015-11-24 22:21 ` Tom Tromey
1 sibling, 1 reply; 59+ messages in thread
From: Daniel Colascione @ 2015-11-24 21:55 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 644 bytes --]
On 11/24/2015 01:34 PM, Paul Eggert wrote:
> On 11/24/2015 12:49 PM, Eli Zaretskii wrote:
>> Btw, using this method the module code becomes very tedious
>
> It's so tedious I can't imagine using it that way. Module authors
> shouldn't have to call env->non_local_exit_check (env) after every
> function call, to see whether the function actually worked. Functions
> should be able to signal an error, just as they can in the Emacs core,
> and the error should propagate through calls in a natural way.
And in a C++ wrapper interface, that can happen naturally and safely. If
you want to write C, you check for errors the C way.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 21:34 ` Paul Eggert
2015-11-24 21:55 ` Daniel Colascione
@ 2015-11-24 22:21 ` Tom Tromey
2015-11-25 6:55 ` Paul Eggert
2015-11-25 18:15 ` Eli Zaretskii
1 sibling, 2 replies; 59+ messages in thread
From: Tom Tromey @ 2015-11-24 22:21 UTC (permalink / raw
To: Paul Eggert
Cc: dancol, tzz, emacs-devel, p.stephani2, aurelien.aptel+emacs,
Eli Zaretskii, Tom Tromey
Paul> It's so tedious I can't imagine using it that way. Module authors
Paul> shouldn't have to call env->non_local_exit_check (env) after every
Paul> function call, to see whether the function actually worked. Functions
Paul> should be able to signal an error, just as they can in the Emacs core,
Paul> and the error should propagate through calls in a natural way.
Yeah, it's tedious.
The alternative is also error-prone though. It's very easy to forget
that some cleanup is needed; and the Emacs facilities here aren't really
all that easy to use either. gdb uses a similar internal system, and it
is better than what Emacs provides, but still error-prone in practice.
Crashing may be the wrong thing to do. Perhaps module APIs should just
fail when the environment is already in the error state.
Tom
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 21:55 ` Daniel Colascione
@ 2015-11-25 6:52 ` Paul Eggert
2015-11-25 7:03 ` Daniel Colascione
0 siblings, 1 reply; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 6:52 UTC (permalink / raw
To: Daniel Colascione, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
Daniel Colascione wrote:
> And in a C++ wrapper interface, that can happen naturally and safely. If
> you want to write C, you check for errors the C way.
C provides multiple ways to check. We're not obliged to implement a tedious and
confusing API, if better alternatives are available.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 22:21 ` Tom Tromey
@ 2015-11-25 6:55 ` Paul Eggert
2015-11-25 17:30 ` Eli Zaretskii
2015-11-25 18:10 ` Tom Tromey
2015-11-25 18:15 ` Eli Zaretskii
1 sibling, 2 replies; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 6:55 UTC (permalink / raw
To: Tom Tromey
Cc: tzz, emacs-devel, p.stephani2, aurelien.aptel+emacs,
Eli Zaretskii, dancol
Tom Tromey wrote:
> The alternative is also error-prone though. It's very easy to forget
> that some cleanup is needed; and the Emacs facilities here aren't really
> all that easy to use either.
We're talking about memory allocation here. If Emacs allocates the memory, the
caller shouldn't need to clean up, as the Emacs garbage collector can do that.
This should be less error-prone.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 6:52 ` Paul Eggert
@ 2015-11-25 7:03 ` Daniel Colascione
2015-11-25 7:14 ` Paul Eggert
0 siblings, 1 reply; 59+ messages in thread
From: Daniel Colascione @ 2015-11-25 7:03 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 445 bytes --]
On 11/24/2015 10:52 PM, Paul Eggert wrote:
> Daniel Colascione wrote:
>> And in a C++ wrapper interface, that can happen naturally and safely. If
>> you want to write C, you check for errors the C way.
>
> C provides multiple ways to check. We're not obliged to implement a
> tedious and confusing API, if better alternatives are available.
C provides many error checking alternatives. Longjmping outside Emacs is
not one of them.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 7:03 ` Daniel Colascione
@ 2015-11-25 7:14 ` Paul Eggert
2015-11-25 7:18 ` Daniel Colascione
0 siblings, 1 reply; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 7:14 UTC (permalink / raw
To: Daniel Colascione, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
Daniel Colascione wrote:
> C provides many error checking alternatives. Longjmping outside Emacs is
> not one of them.
Surely there is a reasonably natural way to address the problem without
requiring module authors to call longjmp, or to have a complex and error-prone
check after every call.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 7:14 ` Paul Eggert
@ 2015-11-25 7:18 ` Daniel Colascione
2015-11-25 7:23 ` Paul Eggert
0 siblings, 1 reply; 59+ messages in thread
From: Daniel Colascione @ 2015-11-25 7:18 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 539 bytes --]
On 11/24/2015 11:14 PM, Paul Eggert wrote:
> Daniel Colascione wrote:
>> C provides many error checking alternatives. Longjmping outside Emacs is
>> not one of them.
>
> Surely there is a reasonably natural way to address the problem without
> requiring module authors to call longjmp, or to have a complex and
> error-prone check after every call.
How is it any worse than checking whether open(2) returns -1? I'd be
fine with just making future calls fail until a module clears the
pending condition or returns to Emacs.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 7:18 ` Daniel Colascione
@ 2015-11-25 7:23 ` Paul Eggert
2015-11-25 7:25 ` Daniel Colascione
0 siblings, 1 reply; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 7:23 UTC (permalink / raw
To: Daniel Colascione, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
Daniel Colascione wrote:
> How is it any worse than checking whether open(2) returns -1?
'open' probes the outside world, and programs should be prepared for such probes
to fail. In contrast, 'cons' is basic memory allocation, just as calling a
function is basic memory allocation. We don't require programs to check each
function call to see whether the call failed because the stack was exhausted.
Similarly we don't require programs to check each call to 'cons' to see whether
'cons' failed because the heap was exhausted.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 7:23 ` Paul Eggert
@ 2015-11-25 7:25 ` Daniel Colascione
2015-11-25 7:49 ` Paul Eggert
0 siblings, 1 reply; 59+ messages in thread
From: Daniel Colascione @ 2015-11-25 7:25 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 818 bytes --]
On 11/24/2015 11:23 PM, Paul Eggert wrote:
> Daniel Colascione wrote:
>> How is it any worse than checking whether open(2) returns -1?
>
> 'open' probes the outside world, and programs should be prepared for
> such probes to fail. In contrast, 'cons' is basic memory allocation,
> just as calling a function is basic memory allocation. We don't require
> programs to check each function call to see whether the call failed
> because the stack was exhausted. Similarly we don't require programs to
> check each call to 'cons' to see whether 'cons' failed because the heap
> was exhausted.
I don't believe in treating memory specially. It's just another
resource. We can exhaust it just like anything else. In elisp, we have
conditions. In a module API, we have to rely on traditional error checking.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 7:25 ` Daniel Colascione
@ 2015-11-25 7:49 ` Paul Eggert
2015-11-25 7:52 ` Daniel Colascione
0 siblings, 1 reply; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 7:49 UTC (permalink / raw
To: Daniel Colascione, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
Daniel Colascione wrote:
> In a module API, we have to rely on traditional error checking.
No we don't. We certainly do not rely on it for checking stack space
exhaustion. And we don't have to rely on it for heap space exhaustion either.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 7:49 ` Paul Eggert
@ 2015-11-25 7:52 ` Daniel Colascione
2015-11-25 7:58 ` Paul Eggert
0 siblings, 1 reply; 59+ messages in thread
From: Daniel Colascione @ 2015-11-25 7:52 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 699 bytes --]
On 11/24/2015 11:49 PM, Paul Eggert wrote:
> Daniel Colascione wrote:
>> In a module API, we have to rely on traditional error checking.
>
> No we don't. We certainly do not rely on it for checking stack space
> exhaustion. And we don't have to rely on it for heap space exhaustion
> either.
What's your alternative? Assuming memory allocation never fails? That's
unacceptable in robust programming. I disagree that it's tedious to
check for allocation failure. We can QUIT almost anywhere too: do you
think we should use some kind of special reporting mechanism for that too?
I don't think having to check for errors is a particularly onerous
requirement when writing C code.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 7:52 ` Daniel Colascione
@ 2015-11-25 7:58 ` Paul Eggert
2015-11-25 8:12 ` Daniel Colascione
0 siblings, 1 reply; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 7:58 UTC (permalink / raw
To: Daniel Colascione, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
Daniel Colascione wrote:
> What's your alternative?
I don't have one right now. But surely a better API can be devised.
I agree that checking errors in return values is reasonable for things like
'open'. But memory allocation is so basic. Plus, the method for checking errors
in the current API is awkward and confusing. It'd be a real turnoff to have to
use it after each little step in one's program.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 7:58 ` Paul Eggert
@ 2015-11-25 8:12 ` Daniel Colascione
2015-11-25 8:24 ` Paul Eggert
0 siblings, 1 reply; 59+ messages in thread
From: Daniel Colascione @ 2015-11-25 8:12 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1817 bytes --]
On 11/24/2015 11:58 PM, Paul Eggert wrote:
> Daniel Colascione wrote:
>> What's your alternative?
>
> I don't have one right now. But surely a better API can be devised.
>
> I agree that checking errors in return values is reasonable for things
> like 'open'. But memory allocation is so basic.
You could argue that file descriptors are basic. They're just handles to
bits of kernel memory, right?
Memory is a resource like anything else, and like all resources, can be
exhausted. (Overcommit is no answer: you can't overcommit address
space.) We have to do _something_ on memory exhaustion, and the only
reasonable choices are communicating the failure up the call stack and
aborting.
Aborting is brittle, so I'd rather not do it. In the Emacs core, we can
activate the low-memory code and let users save work, but if we abort
because a module asks us to allocate, we'll lose data.
> Plus, the method for
> checking errors in the current API is awkward and confusing. It'd be a
> real turnoff to have to use it after each little step in one's program.
Well, there's the Xlib method, where calls just silently fail until you
bother checking for error. I think that's even more cumbersome, since it
makes isolating the source of an error difficult unless your program
runs in synchronous mode.
Lots of extension APIs require error checks. Python's in particular
comes to mind. Using these APIs doesn't feel particularly onerous.
That said, I agree that the specific API for error checking is
cumbersome. The function name is long, and comparing the value it
returns to a specific sentinel feels awkward. IMHO, we could simplify it
to if(env->error_p(env)) { return NULL; } (The name "error" here isn't
strictly accurate, but I think it's close enough, and it's short.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 8:12 ` Daniel Colascione
@ 2015-11-25 8:24 ` Paul Eggert
2015-11-25 8:50 ` Daniel Colascione
0 siblings, 1 reply; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 8:24 UTC (permalink / raw
To: Daniel Colascione, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
Daniel Colascione wrote:
> You could argue that file descriptors are basic. They're just handles to
> bits of kernel memory, right?
I'm not making that argument. I am arguing that memory allocation is basic,
though. It really is. It happens *all the time* in the C code inside Emacs, and
it's almost surely going to happen all the time in module code as well. It
should be easy, not a pain.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 8:24 ` Paul Eggert
@ 2015-11-25 8:50 ` Daniel Colascione
2015-11-25 9:11 ` Daniel Colascione
2015-11-25 17:34 ` Paul Eggert
0 siblings, 2 replies; 59+ messages in thread
From: Daniel Colascione @ 2015-11-25 8:50 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2236 bytes --]
On 11/25/2015 12:24 AM, Paul Eggert wrote:
> Daniel Colascione wrote:
>> You could argue that file descriptors are basic. They're just handles to
>> bits of kernel memory, right?
>
> I'm not making that argument. I am arguing that memory allocation is
> basic, though. It really is. It happens *all the time* in the C code
> inside Emacs, and it's almost surely going to happen all the time in
> module code as well. It should be easy, not a pain.
Modules in C already have to handle checking for failures of their
internal allocations. What makes checking for failures of Emacs-side
allocations so much worse?
There are ways of making working with Lisp easier while preserving
robustness. I've previously proposed providing a utility function that
lets callers write expressions like this:
emacs_value v =
env->eval_fmt(env, "`(foo (xyz . bar) ,%v ,%s ,(something %d))",
my_emacs_value, "blah", 42);
if(!v) { return NULL; } // Equivalently, if (env->error_p(env)) { return
NULL; }
do_something_with(v);
It's possible to implement eval_fmt mostly in Lisp, and it would let C
callers naturally construct arbitrarily complicated Lisp data structures
while only checking for errors in one place. Sure, it's not the fastest
thing the world, but in hot spots, modules can always drop down to the
very exact, but very verbose, API we've been complaining about here.
It should also be possible to write a function that pulls values out of
existing data structures just like destructuring-bind ---
char* key;
int value;
emacs_value some_plist = mumble;
while (env->is_not_nil(some_plist) && env->extract_fmt(env, some_plist,
"(%s %d . %v)", &key, &value, &some_plist)) {
do_something(key, value);
env->emacs_free(key); // extract_fmt allocated memory for the contents
of the string key using the internal emacs allocator
}
if (env->error_p(env)) {
return NULL;
}
This way, it's possible to do fairly involved things while not checking
for errors at every single step.
It's also possible to implement eval_fmt and extract_fmt as library
functions written in terms of the current module API, but it wouldn't
hurt to provide them directly for the convenience of C callers.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 8:50 ` Daniel Colascione
@ 2015-11-25 9:11 ` Daniel Colascione
2015-11-25 18:19 ` Eli Zaretskii
2015-11-25 18:26 ` Philipp Stephani
2015-11-25 17:34 ` Paul Eggert
1 sibling, 2 replies; 59+ messages in thread
From: Daniel Colascione @ 2015-11-25 9:11 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1544 bytes --]
On 11/25/2015 12:50 AM, Daniel Colascione wrote:
> On 11/25/2015 12:24 AM, Paul Eggert wrote:
>> Daniel Colascione wrote:
>>> You could argue that file descriptors are basic. They're just handles to
>>> bits of kernel memory, right?
>>
>> I'm not making that argument. I am arguing that memory allocation is
>> basic, though. It really is. It happens *all the time* in the C code
>> inside Emacs, and it's almost surely going to happen all the time in
>> module code as well. It should be easy, not a pain.
>
> Modules in C already have to handle checking for failures of their
> internal allocations. What makes checking for failures of Emacs-side
> allocations so much worse?
>
> There are ways of making working with Lisp easier while preserving
> robustness.
Another option for making the Emacs API more ergonomic might be to
define most functions to do nothing if we have non-local control flow
pending, even on otherwise-invalid inputs. (That's opposed to making
emacs_env calls with pending non-local control into a programming
error.) That way, you'd be able to write something like this...
int64_t vplus1 = env->extract_integer(env, env->eval_fmt(env, "(1+ blah
%v)", v));
if (env->error_p()) {
return NULL;
}
... and preserve whatever went wrong inside eval_fmt, not abort or raise
some generic "invalid call to extract_integer" error.
I'm not sure that this scheme is a good idea, but it does make for
shorter code while still allowing us to propagate errors from any spot
inside Emacs.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 6:55 ` Paul Eggert
@ 2015-11-25 17:30 ` Eli Zaretskii
2015-11-25 17:34 ` Paul Eggert
2015-11-25 18:10 ` Tom Tromey
1 sibling, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-25 17:30 UTC (permalink / raw
To: Paul Eggert
Cc: dancol, tzz, emacs-devel, p.stephani2, aurelien.aptel+emacs, tom
> Cc: Eli Zaretskii <eliz@gnu.org>, aurelien.aptel+emacs@gmail.com,
> p.stephani2@gmail.com, dancol@dancol.org, tzz@lifelogs.com,
> emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Tue, 24 Nov 2015 22:55:14 -0800
>
> Tom Tromey wrote:
> > The alternative is also error-prone though. It's very easy to forget
> > that some cleanup is needed; and the Emacs facilities here aren't really
> > all that easy to use either.
>
> We're talking about memory allocation here. If Emacs allocates the memory, the
> caller shouldn't need to clean up, as the Emacs garbage collector can do that.
> This should be less error-prone.
Maybe I misunderstand the issue, but AFAICS any Lisp data that is
allocated by emacs-module.c on behalf of modules already goes through
xmalloc, so what exactly are the remaining problems?
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 17:30 ` Eli Zaretskii
@ 2015-11-25 17:34 ` Paul Eggert
2015-11-25 21:23 ` Stefan Monnier
0 siblings, 1 reply; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 17:34 UTC (permalink / raw
To: Eli Zaretskii
Cc: dancol, tzz, emacs-devel, p.stephani2, aurelien.aptel+emacs, tom
On 11/25/2015 09:30 AM, Eli Zaretskii wrote:
> Maybe I misunderstand the issue, but AFAICS any Lisp data that is
> allocated by emacs-module.c on behalf of modules already goes through
> xmalloc, so what exactly are the remaining problems?
I think Daniel is worried that module code will call xmalloc, and then
do more work that signals an Elisp error or throws a C++ exception, and
the module will then leak the xmalloced memory. There may be other
concerns like that too, but I'm not sure what they are.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 8:50 ` Daniel Colascione
2015-11-25 9:11 ` Daniel Colascione
@ 2015-11-25 17:34 ` Paul Eggert
1 sibling, 0 replies; 59+ messages in thread
From: Paul Eggert @ 2015-11-25 17:34 UTC (permalink / raw
To: Daniel Colascione, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, p.stephani2, tzz, emacs-devel
On 11/25/2015 12:50 AM, Daniel Colascione wrote:
> Modules in C already have to handle checking for failures of their
> internal allocations. What makes checking for failures of Emacs-side
> allocations so much worse?
Allocation is more-common in Lisp-like programs than in C-like programs,
so it needs to be catered to more. Traditionally, C dynamic allocation
was often done on the stack, where the programmer doesn't need to
manually insert code to check whether it succeeds. Lisp and module code
should be as convenient as that, for 'cons'.
This raises another issue, though. Suppose Emacs detects C stack
overflow and signals an exception when in the middle of a module. How
does that work? We need to solve the stack-exhaustion problem
independently of the details of the module API for memory allocation.
And whatever method we come up with, should make it easier for us to
provide convenient heap allocation too, because stack and heap
exhaustion can be handled by similar mechanisms.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 19:41 Dynamic modules: emacs-module.c and signaling errors Eli Zaretskii
2015-11-24 19:45 ` Eli Zaretskii
2015-11-24 20:12 ` Tom Tromey
@ 2015-11-25 18:09 ` Philipp Stephani
2015-11-25 21:19 ` Stefan Monnier
2 siblings, 1 reply; 59+ messages in thread
From: Philipp Stephani @ 2015-11-25 18:09 UTC (permalink / raw
To: Eli Zaretskii, aurelien.aptel+emacs, tzz, dancol; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2188 bytes --]
Eli Zaretskii <eliz@gnu.org> schrieb am Di., 24. Nov. 2015 um 20:41 Uhr:
> In "emacs -Q", load the modules/mod-test/mod-test module, then try
> this:
>
> M-: (mod-test-sum "1" 2) RET
>
> Result: Emacs aborts. This happens because the eassert in
> module_extract_integer aborts, when that function is called for the
> 2nd time:
>
> static intmax_t
> module_extract_integer (emacs_env *env, emacs_value n)
> {
> check_main_thread ();
> eassert (module_non_local_exit_check (env) ==
> emacs_funcall_exit_return);
> Lisp_Object l = value_to_lisp (n);
> if (! INTEGERP (l))
> {
> module_wrong_type (env, Qintegerp, l);
> return 0;
> }
>
> The first call to module_extract_integer correctly detects the wrong
> type of argument and calls module_wrong_type. But module_wrong_type
> just records the problem in the env structure, it doesn't signal any
> Lisp error, like an Emacs primitive would. So the actual error goes
> undetected, and is masked by the assertion violation (because Emacs is
> built with --enable-checking).
>
> Since this obviously works as it was designed, my question is: how
> should a module be written so that this kind of errors signal a normal
> Lisp error we are accustomed with Emacs primitives?
>
>
I still need to fix most of the example module (unfortunately that was
written before the error handling got implemented), but the gist is that
functions returning emacs_value should usually be called like this:
emacs_value ret = env->foo(env, ...);
if (ret == NULL) return NULL;
This will cause errors to be reported back to Emacs, where they are thrown
as normal signals.
I have thought about how we can prevent some accidental misuse. I propose
that all environment functions should have a signature like this:
__attribute__((warn_unused_result))
bool (*func)(emacs_env *env, ..., result_type* result);
instead of returning result directly. This way users get a warning if they
forget to check for errors. The above example would then turn into:
emacs_value ret;
if (!env->foo(env, ..., &ret)) return false;
which isn't worse, but avoids sentinel values and makes the API harder to
misuse. Thoughts?
[-- Attachment #2: Type: text/html, Size: 2815 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 6:55 ` Paul Eggert
2015-11-25 17:30 ` Eli Zaretskii
@ 2015-11-25 18:10 ` Tom Tromey
1 sibling, 0 replies; 59+ messages in thread
From: Tom Tromey @ 2015-11-25 18:10 UTC (permalink / raw
To: Paul Eggert
Cc: dancol, tzz, emacs-devel, p.stephani2, aurelien.aptel+emacs,
Eli Zaretskii, Tom Tromey
>>>>> "Paul" == Paul Eggert <eggert@cs.ucla.edu> writes:
Paul> Tom Tromey wrote:
>> The alternative is also error-prone though. It's very easy to forget
>> that some cleanup is needed; and the Emacs facilities here aren't really
>> all that easy to use either.
Paul> We're talking about memory allocation here. If Emacs allocates the
Paul> memory, the caller shouldn't need to clean up, as the Emacs garbage
Paul> collector can do that. This should be less error-prone.
The particular problem Eli mentioned was not memory allocation, it was a
type-checking error. In particular see how module_extract_integer calls
module_wrong_type.
Tom
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-24 22:21 ` Tom Tromey
2015-11-25 6:55 ` Paul Eggert
@ 2015-11-25 18:15 ` Eli Zaretskii
1 sibling, 0 replies; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-25 18:15 UTC (permalink / raw
To: Tom Tromey
Cc: eggert, dancol, tzz, emacs-devel, p.stephani2,
aurelien.aptel+emacs, tom
> From: Tom Tromey <tom@tromey.com>
> Cc: Eli Zaretskii <eliz@gnu.org>, Tom Tromey <tom@tromey.com>, aurelien.aptel+emacs@gmail.com, p.stephani2@gmail.com, dancol@dancol.org, tzz@lifelogs.com, emacs-devel@gnu.org
> Date: Tue, 24 Nov 2015 15:21:20 -0700
>
> Perhaps module APIs should just fail when the environment is already
> in the error state.
Thanks, I think this is a very simple measure that goes a long way
towards resolving the issue.
Any objections to installing the patch below? With it, I can get the
expected Lisp error when invoking the unchanged mod-test-sum with
non-integer arguments.
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 1388e53..c75ddeb 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -198,7 +198,8 @@ static void module_wrong_type (emacs_env *, Lisp_Object, Lisp_Object);
its local variable C must stay live in later code. */
#define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c, dummy) \
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return); \
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return) \
+ return retval; \
struct handler *c = push_handler_nosignal (Qt, handlertype); \
if (!c) \
{ \
@@ -256,7 +288,8 @@ static emacs_value
module_make_global_ref (emacs_env *env, emacs_value ref)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
MODULE_HANDLE_SIGNALS;
struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
Lisp_Object new_obj = value_to_lisp (ref);
@@ -287,7 +320,8 @@ static void
module_free_global_ref (emacs_env *env, emacs_value ref)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return;
/* TODO: This probably never signals. */
/* FIXME: Wait a minute. Shouldn't this function report an error if
the hash lookup fails? */
@@ -343,18 +377,18 @@ static void
module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
- module_non_local_exit_signal_1 (env, value_to_lisp (sym),
- value_to_lisp (data));
+ if (module_non_local_exit_check (env) == emacs_funcall_exit_return)
+ module_non_local_exit_signal_1 (env, value_to_lisp (sym),
+ value_to_lisp (data));
}
static void
module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
- module_non_local_exit_throw_1 (env, value_to_lisp (tag),
- value_to_lisp (value));
+ if (module_non_local_exit_check (env) == emacs_funcall_exit_return)
+ module_non_local_exit_throw_1 (env, value_to_lisp (tag),
+ value_to_lisp (value));
}
/* A module function is lambda function that calls `module-call',
@@ -370,7 +404,8 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity,
void *data)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
MODULE_HANDLE_SIGNALS;
if (! (0 <= min_arity
@@ -407,7 +442,8 @@ module_funcall (emacs_env *env, emacs_value fun, ptrdiff_t nargs,
emacs_value args[])
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
MODULE_HANDLE_SIGNALS;
MODULE_HANDLE_THROW;
@@ -428,7 +464,8 @@ static emacs_value
module_intern (emacs_env *env, const char *name)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
MODULE_HANDLE_SIGNALS;
return lisp_to_value (env, intern (name));
}
@@ -437,7 +474,8 @@ static emacs_value
module_type_of (emacs_env *env, emacs_value value)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
return lisp_to_value (env, Ftype_of (value_to_lisp (value)));
}
@@ -445,7 +483,8 @@ static bool
module_is_not_nil (emacs_env *env, emacs_value value)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return false;
return ! NILP (value_to_lisp (value));
}
@@ -453,7 +492,8 @@ static bool
module_eq (emacs_env *env, emacs_value a, emacs_value b)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return false;
return EQ (value_to_lisp (a), value_to_lisp (b));
}
@@ -461,7 +501,8 @@ static intmax_t
module_extract_integer (emacs_env *env, emacs_value n)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return 0;
Lisp_Object l = value_to_lisp (n);
if (! INTEGERP (l))
{
@@ -475,7 +516,8 @@ static emacs_value
module_make_integer (emacs_env *env, intmax_t n)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
if (! (MOST_NEGATIVE_FIXNUM <= n && n <= MOST_POSITIVE_FIXNUM))
{
module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
@@ -488,7 +530,8 @@ static double
module_extract_float (emacs_env *env, emacs_value f)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return 0;
Lisp_Object lisp = value_to_lisp (f);
if (! FLOATP (lisp))
{
@@ -502,7 +545,8 @@ static emacs_value
module_make_float (emacs_env *env, double d)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
MODULE_HANDLE_SIGNALS;
return lisp_to_value (env, make_float (d));
}
@@ -512,7 +556,8 @@ module_copy_string_contents (emacs_env *env, emacs_value value, char *buffer,
ptrdiff_t *length)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return false;
MODULE_HANDLE_SIGNALS;
Lisp_Object lisp_str = value_to_lisp (value);
if (! STRINGP (lisp_str))
@@ -557,7 +602,8 @@ static emacs_value
module_make_string (emacs_env *env, const char *str, ptrdiff_t length)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
MODULE_HANDLE_SIGNALS;
if (length > STRING_BYTES_BOUND)
{
@@ -573,6 +619,8 @@ static emacs_value
module_make_user_ptr (emacs_env *env, emacs_finalizer_function fin, void *ptr)
{
check_main_thread ();
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
return lisp_to_value (env, make_user_ptr (fin, ptr));
}
@@ -580,7 +628,8 @@ static void *
module_get_user_ptr (emacs_env *env, emacs_value uptr)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
Lisp_Object lisp = value_to_lisp (uptr);
if (! USER_PTRP (lisp))
{
@@ -594,7 +643,8 @@ static void
module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return;
Lisp_Object lisp = value_to_lisp (uptr);
if (! USER_PTRP (lisp))
module_wrong_type (env, Quser_ptr, lisp);
@@ -605,7 +655,8 @@ static emacs_finalizer_function
module_get_user_finalizer (emacs_env *env, emacs_value uptr)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
Lisp_Object lisp = value_to_lisp (uptr);
if (! USER_PTRP (lisp))
{
@@ -620,7 +671,8 @@ module_set_user_finalizer (emacs_env *env, emacs_value uptr,
emacs_finalizer_function fin)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return;
Lisp_Object lisp = value_to_lisp (uptr);
if (! USER_PTRP (lisp))
module_wrong_type (env, Quser_ptr, lisp);
@@ -631,7 +683,8 @@ static void
module_vec_set (emacs_env *env, emacs_value vec, ptrdiff_t i, emacs_value val)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return;
Lisp_Object lvec = value_to_lisp (vec);
if (! VECTORP (lvec))
{
@@ -653,7 +706,8 @@ static emacs_value
module_vec_get (emacs_env *env, emacs_value vec, ptrdiff_t i)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return NULL;
Lisp_Object lvec = value_to_lisp (vec);
if (! VECTORP (lvec))
{
@@ -675,7 +729,8 @@ static ptrdiff_t
module_vec_size (emacs_env *env, emacs_value vec)
{
check_main_thread ();
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
+ if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
+ return 0;
Lisp_Object lvec = value_to_lisp (vec);
if (! VECTORP (lvec))
{
@@ -806,10 +861,12 @@ module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym,
Lisp_Object data)
{
struct emacs_env_private *p = env->private_members;
- eassert (p->pending_non_local_exit == emacs_funcall_exit_return);
- p->pending_non_local_exit = emacs_funcall_exit_signal;
- p->non_local_exit_symbol.v = sym;
- p->non_local_exit_data.v = data;
+ if (p->pending_non_local_exit == emacs_funcall_exit_return)
+ {
+ p->pending_non_local_exit = emacs_funcall_exit_signal;
+ p->non_local_exit_symbol.v = sym;
+ p->non_local_exit_data.v = data;
+ }
}
static void
@@ -817,10 +874,12 @@ module_non_local_exit_throw_1 (emacs_env *env, Lisp_Object tag,
Lisp_Object value)
{
struct emacs_env_private *p = env->private_members;
- eassert (p->pending_non_local_exit == emacs_funcall_exit_return);
- p->pending_non_local_exit = emacs_funcall_exit_throw;
- p->non_local_exit_symbol.v = tag;
- p->non_local_exit_data.v = value;
+ if (p->pending_non_local_exit == emacs_funcall_exit_return)
+ {
+ p->pending_non_local_exit = emacs_funcall_exit_throw;
+ p->non_local_exit_symbol.v = tag;
+ p->non_local_exit_data.v = value;
+ }
}
/* Module version of `wrong_type_argument'. */
^ permalink raw reply related [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 9:11 ` Daniel Colascione
@ 2015-11-25 18:19 ` Eli Zaretskii
2015-11-25 18:26 ` Philipp Stephani
1 sibling, 0 replies; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-25 18:19 UTC (permalink / raw
To: Daniel Colascione
Cc: eggert, tzz, emacs-devel, p.stephani2, aurelien.aptel+emacs, tom
> Cc: aurelien.aptel+emacs@gmail.com, p.stephani2@gmail.com, tzz@lifelogs.com,
> emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Wed, 25 Nov 2015 01:11:16 -0800
>
> Another option for making the Emacs API more ergonomic might be to
> define most functions to do nothing if we have non-local control flow
> pending, even on otherwise-invalid inputs.
That's what AFAIU Tom suggested, and I tried to implement in a patch
sent a few minutes ago. Please take a look.
> I'm not sure that this scheme is a good idea
Why not?
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 9:11 ` Daniel Colascione
2015-11-25 18:19 ` Eli Zaretskii
@ 2015-11-25 18:26 ` Philipp Stephani
2015-11-25 19:19 ` Eli Zaretskii
1 sibling, 1 reply; 59+ messages in thread
From: Philipp Stephani @ 2015-11-25 18:26 UTC (permalink / raw
To: Daniel Colascione, Paul Eggert, Eli Zaretskii, Tom Tromey
Cc: aurelien.aptel+emacs, tzz, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2372 bytes --]
Daniel Colascione <dancol@dancol.org> schrieb am Mi., 25. Nov. 2015 um
10:11 Uhr:
> On 11/25/2015 12:50 AM, Daniel Colascione wrote:
> > On 11/25/2015 12:24 AM, Paul Eggert wrote:
> >> Daniel Colascione wrote:
> >>> You could argue that file descriptors are basic. They're just handles
> to
> >>> bits of kernel memory, right?
> >>
> >> I'm not making that argument. I am arguing that memory allocation is
> >> basic, though. It really is. It happens *all the time* in the C code
> >> inside Emacs, and it's almost surely going to happen all the time in
> >> module code as well. It should be easy, not a pain.
> >
> > Modules in C already have to handle checking for failures of their
> > internal allocations. What makes checking for failures of Emacs-side
> > allocations so much worse?
> >
> > There are ways of making working with Lisp easier while preserving
> > robustness.
>
> Another option for making the Emacs API more ergonomic might be to
> define most functions to do nothing if we have non-local control flow
> pending, even on otherwise-invalid inputs. (That's opposed to making
> emacs_env calls with pending non-local control into a programming
> error.) That way, you'd be able to write something like this...
>
> int64_t vplus1 = env->extract_integer(env, env->eval_fmt(env, "(1+ blah
> %v)", v));
> if (env->error_p()) {
> return NULL;
> }
>
> ... and preserve whatever went wrong inside eval_fmt, not abort or raise
> some generic "invalid call to extract_integer" error.
>
> I'm not sure that this scheme is a good idea, but it does make for
> shorter code while still allowing us to propagate errors from any spot
> inside Emacs.
>
>
I'm not a fan of this idea. It is unlike all other C APIs I'm aware of and
I think the behavior would be quite surprising to the module author. After
all, it causes code to silently do nothing if doing something was requested.
I see a couple of alternatives:
- If an unhandled error is detected, crash unconditionally, even if
checking is disabled. This would be consistent with the behavior of
structured exceptions in popular programming languages, and would make bugs
very obvious.
- Ignore unhandled errors, proceed as if no error happened. This would be
consistent with popular C APIs such a the C standard library itself and
POSIX.
- The current approach: crash if checking is enabled, ignore otherwise.
[-- Attachment #2: Type: text/html, Size: 2947 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 18:26 ` Philipp Stephani
@ 2015-11-25 19:19 ` Eli Zaretskii
2015-11-25 21:52 ` Philipp Stephani
0 siblings, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-25 19:19 UTC (permalink / raw
To: Philipp Stephani
Cc: tom, tzz, emacs-devel, eggert, aurelien.aptel+emacs, dancol
> From: Philipp Stephani <p.stephani2@gmail.com>
> Date: Wed, 25 Nov 2015 18:26:31 +0000
> Cc: aurelien.aptel+emacs@gmail.com, tzz@lifelogs.com, emacs-devel@gnu.org
>
> I see a couple of alternatives:
> - If an unhandled error is detected, crash unconditionally, even if checking is
> disabled.
What do you mean by "crash"? Abort? That's unacceptable: Emacs
should not abort because some module misbehaved. A long-lived Emacs
session holds gobs of precious data and state, utterly unrelated to
what a module tried to do, so discarding all that because of some
programming error in some module would be unthinkable.
We should cause such errors signal an error (eventually), like any
Lisp code does.
> - Ignore unhandled errors, proceed as if no error happened. This would be
> consistent with popular C APIs such a the C standard library itself and POSIX.
> - The current approach: crash if checking is enabled, ignore otherwise.
The simple patch I sent a few minutes ago, according to Tom's
suggestion, should cause such errors to signal a Lisp error from
module-call. I think this is what we should do.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 18:09 ` Philipp Stephani
@ 2015-11-25 21:19 ` Stefan Monnier
2015-11-26 15:41 ` Eli Zaretskii
0 siblings, 1 reply; 59+ messages in thread
From: Stefan Monnier @ 2015-11-25 21:19 UTC (permalink / raw
To: emacs-devel
I'll just mention that having to learn a whole new way to run Elisp
functions when writing module code instead of core code just
sucks rocks!
It presumes Emacs modules are mainly written by non-Emacs developers.
And it makes it harder for module writers to graduate to
Emacs contributors.
Not to mention that it makes the interface between Emacs modules and
Emacs core less efficient.
> The alternative is also error-prone though. It's very easy to forget
> that some cleanup is needed;
The alternative is what we use inside Emacs core. Maybe it's not
perfect but it worked fine for the last 30 years, with interfaces to
fairly varied libraries, like libX11, libxml2, libgnutls, ...
I think it has a pretty good track record.
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 17:34 ` Paul Eggert
@ 2015-11-25 21:23 ` Stefan Monnier
2015-11-26 15:42 ` Eli Zaretskii
0 siblings, 1 reply; 59+ messages in thread
From: Stefan Monnier @ 2015-11-25 21:23 UTC (permalink / raw
To: emacs-devel
> I think Daniel is worried that module code will call xmalloc, and then do
> more work that signals an Elisp error or throws a C++ exception, and the
> module will then leak the xmalloced memory. There may be other concerns like
> that too, but I'm not sure what they are.
I find it hard to believe that we'd follow Daniel's recommendation
over mine. As far as I know, he didn't give any more evidence of his
assertions of goodness of his approach than I did (OTOH, it's obvious at
the technical level that Daniel's approach can be layered on top of
mine, whereas the reverse is not true, which I think should a strong
argument in favor of following the simpler approach I advocate).
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 19:19 ` Eli Zaretskii
@ 2015-11-25 21:52 ` Philipp Stephani
0 siblings, 0 replies; 59+ messages in thread
From: Philipp Stephani @ 2015-11-25 21:52 UTC (permalink / raw
To: Eli Zaretskii; +Cc: tom, tzz, emacs-devel, eggert, aurelien.aptel+emacs, dancol
[-- Attachment #1: Type: text/plain, Size: 1066 bytes --]
Eli Zaretskii <eliz@gnu.org> schrieb am Mi., 25. Nov. 2015 um 20:19 Uhr:
> > - Ignore unhandled errors, proceed as if no error happened. This would be
> > consistent with popular C APIs such a the C standard library itself and
> POSIX.
> > - The current approach: crash if checking is enabled, ignore otherwise.
>
> The simple patch I sent a few minutes ago, according to Tom's
> suggestion, should cause such errors to signal a Lisp error from
> module-call. I think this is what we should do.
>
Yes, I think that's better than crashing, longjmping, and also the current
approach. Ignoring unhandled errors would indeed have the potential to
swallow errors, unless we saturate the error state (i.e. never set it to
successful except in clear_error). So now I think that your patch indeed is
the best solution.
Maybe we should further reduce the amount of undefined behavior. Currently
e.g. passing null pointers is undefined behavior that will typically crash
Emacs. We could make this more robust by signaling an error instead; the
overhead should be minimal.
[-- Attachment #2: Type: text/html, Size: 1391 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 21:19 ` Stefan Monnier
@ 2015-11-26 15:41 ` Eli Zaretskii
0 siblings, 0 replies; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-26 15:41 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Wed, 25 Nov 2015 16:19:37 -0500
>
> I'll just mention that having to learn a whole new way to run Elisp
> functions when writing module code instead of core code just
> sucks rocks!
>
> It presumes Emacs modules are mainly written by non-Emacs developers.
> And it makes it harder for module writers to graduate to
> Emacs contributors.
I agree that having an entirely different paradigm would be
sub-optimal, to say the least. But I don't quite see it happening in
this case.
What are the main differences between writing core C code and module C
code? Here's what I see:
. The need to call Emacs functions via a pointer.
IOW, instead of calling, say, 'intern', you need to call
'env->intern' instead.
This is not a terrible pain, IMO, and we could make it even less
so, with 2 measures:
- Make all the functions in the API have the same names as their
Emacs siblings.
Most of them already are; for the rest, we could change the
names, so that, e.g., vec_size is called ASIZE and vec_set is
called ASET.
- Have emacs-module.h define macros that would eliminate the
'env->' part altogether, so that you can just call 'intern',
'ASET', etc.
. Lisp objects are declared as 'emacs_value' instead of
'Lisp_Object'.
Once again, we could rename the 'emacs_value' typedef to, say,
'module_Lisp_Object' or some such. (I don't recommend using
'Lisp_Object', because IMO we should make the distinction
explicit.)
. You cannot freely assign Lisp objects.
IOW, instead of this:
Lisp_Object foo = Vsome_variable;
you need to do this:
emacs_value foo = env->intern (env, "some-variable");
and similarly with function calls:
emacs_value bar = env->funcall (env, env->intern (env, "list"), 3, args);
But again, with some minimal syntactic sugar, like
emacs_value Qlist = env->intern (env, "list");
you can almost have the core syntax back. And uses of Vfoo in the
core is possible because we do
Vfoo = intern ("foo");
in the initialization code; modules could do the same in their
init function, and then they'll have this sugar as well.
. A different (and somewhat awkward) way of doing the equivalent of
DEFUN and 'provide'.
I think we should have macros MODULE_DEFUN and MODULE_PROVIDE for
this. They are straightforward to write. I don't think it's
reasonable to ask each module author to invent the code one can
see near the end of mod-test.c, it's fairly boilerplate, and will
most probably be present in any module hence.
. Signaling an error and 'throw'
Once again, we should wrap them into convenient macros that look
similar enough to a call to xsignal or Fthrow.
Are there any other problems?
Maybe you are thinking about emacs-module.c itself. It does include
some fairly arcane code that is meant to support what was deemed as a
safer interface. But emacs-module.c is a small file, so I think we
can sustain its somewhat unusual techniques, especially if we add
there a commentary with detailed rules for how each function there
should be written.
> Not to mention that it makes the interface between Emacs modules and
> Emacs core less efficient.
Maybe I'm missing something, but I don't see it that way. The
interface between the core and a module is the normal Lisp
interpreter; once the module's functions and global variables are
registered, they are just normal Lisp functions and variables. Is
this incorrect?
The module implementation itself is indeed slightly less efficient
than if we'd code the same functionality directly in core. But so
what? it's still very close to raw C efficiency, and paying a small
price for the extensibility is well worth it, I think.
> > The alternative is also error-prone though. It's very easy to forget
> > that some cleanup is needed;
>
> The alternative is what we use inside Emacs core. Maybe it's not
> perfect but it worked fine for the last 30 years, with interfaces to
> fairly varied libraries, like libX11, libxml2, libgnutls, ...
> I think it has a pretty good track record.
That's not really an alternative, as doing that means you'd need to
recompile Emacs after adding code to core.
The real question is: what is the alternative _interface_ between
Emacs and the modules that would look like what we do with GnuTLS
etc.? Do you mean we should have exported all the internal Emacs
functions, and let modules call them directly? Or do you mean
something else? IOW, you'd have to present a fairly complete
alternative design, before we could be able to discuss an alternative.
And all those libraries you've mentioned don't need any cleanup when
application code longjmp's. So this, too, will have to be part of any
alternative design.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-25 21:23 ` Stefan Monnier
@ 2015-11-26 15:42 ` Eli Zaretskii
2015-11-26 16:36 ` Stefan Monnier
0 siblings, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-26 15:42 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Wed, 25 Nov 2015 16:23:24 -0500
>
> > I think Daniel is worried that module code will call xmalloc, and then do
> > more work that signals an Elisp error or throws a C++ exception, and the
> > module will then leak the xmalloced memory. There may be other concerns like
> > that too, but I'm not sure what they are.
>
> I find it hard to believe that we'd follow Daniel's recommendation
> over mine. As far as I know, he didn't give any more evidence of his
> assertions of goodness of his approach than I did (OTOH, it's obvious at
> the technical level that Daniel's approach can be layered on top of
> mine, whereas the reverse is not true, which I think should a strong
> argument in favor of following the simpler approach I advocate).
Are you talking about signaling and throwing in case of errors? Or
are you talking about something else?
I think we should be pragmatic here. If there's a way of having an
interface that is safe in the face of the likes of C++ exceptions,
without unduly punishing module authors, we should take it. It sounds
like a win-win to me.
I believe we've already found a reasonably good way to handle
signaling errors and throwing. (I will soon install the changes I
posted yesterday.) With that in place, module code that wants to
signal an error will look very much like what we do in core in similar
situations.
Paul wants to extend these conveniences to memory allocation, and that
is what he wrote about above. I agree it would be nice to have that.
I'm not sure I fully understand the concerns (Paul says he doesn't
understand them fully, either), but with my perhaps limited
understanding, I fail to see why the same approach -- save the
information about the Lisp error in the environment object, then
return instead of jumping, and let module-call signal -- cannot be
used to provide a convenient memory allocator very similar to xmalloc.
At worst, we will just need to teach emacs-module.c about the
"memory-full" error, that's all.
Am I missing something?
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 15:42 ` Eli Zaretskii
@ 2015-11-26 16:36 ` Stefan Monnier
2015-11-26 17:08 ` Eli Zaretskii
0 siblings, 1 reply; 59+ messages in thread
From: Stefan Monnier @ 2015-11-26 16:36 UTC (permalink / raw
To: Eli Zaretskii; +Cc: emacs-devel
> Are you talking about signaling and throwing in case of errors?
Yes, that's the only issue at stake.
> I think we should be pragmatic here. If there's a way of having an
> interface that is safe in the face of the likes of C++ exceptions,
> without unduly punishing module authors, we should take it.
The interface we expose is a C interface.
We could add a C++ interface on top of it, of course, but I think we
should first focus on interfacing with C code.
> I believe we've already found a reasonably good way to handle
> signaling errors and throwing. (I will soon install the changes I
> posted yesterday.) With that in place, module code that wants to
> signal an error will look very much like what we do in core in similar
> situations.
The issue at stake is when module code calls an Emacs function that
signals an error. In the basic API this signal should not be caught by
the module API (i.e. Emacs's Fsignal code will happily longjmp out of
the modules code when applicable), unless explicitly requested via
something like env->safe_funcall.
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 16:36 ` Stefan Monnier
@ 2015-11-26 17:08 ` Eli Zaretskii
2015-11-26 19:28 ` Stefan Monnier
0 siblings, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-26 17:08 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> Cc: emacs-devel@gnu.org
> Date: Thu, 26 Nov 2015 11:36:00 -0500
>
> The issue at stake is when module code calls an Emacs function that
> signals an error. In the basic API this signal should not be caught by
> the module API (i.e. Emacs's Fsignal code will happily longjmp out of
> the modules code when applicable), unless explicitly requested via
> something like env->safe_funcall.
What happens now is that modules can call Lisp only via env->funcall,
which _will_ catch the signal. When the signal is caught, its data is
recorded. All the other API calls made by the module function on
whose watch the signal happened will do nothing, and eventually the
module function will return to module-call, which will re-throw the
signal with exactly the same data.
Why is that a problem?
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 17:08 ` Eli Zaretskii
@ 2015-11-26 19:28 ` Stefan Monnier
2015-11-26 19:34 ` Eli Zaretskii
0 siblings, 1 reply; 59+ messages in thread
From: Stefan Monnier @ 2015-11-26 19:28 UTC (permalink / raw
To: Eli Zaretskii; +Cc: emacs-devel
> What happens now is that modules can call Lisp only via env->funcall,
> which _will_ catch the signal. When the signal is caught, its data is
> recorded. All the other API calls made by the module function on
> whose watch the signal happened will do nothing, and eventually the
> module function will return to module-call, which will re-throw the
> signal with exactly the same data.
> Why is that a problem?
Because this loses the connection between the signal and its origin.
Because it imposes a cost which we may not want to pay.
The current "funcall" should be renamed to "safe_funcall", and a new
"funcall" should be provided which does not catch signals.
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 19:28 ` Stefan Monnier
@ 2015-11-26 19:34 ` Eli Zaretskii
2015-11-26 20:11 ` Stefan Monnier
0 siblings, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-26 19:34 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> Cc: emacs-devel@gnu.org
> Date: Thu, 26 Nov 2015 14:28:34 -0500
>
> > What happens now is that modules can call Lisp only via env->funcall,
> > which _will_ catch the signal. When the signal is caught, its data is
> > recorded. All the other API calls made by the module function on
> > whose watch the signal happened will do nothing, and eventually the
> > module function will return to module-call, which will re-throw the
> > signal with exactly the same data.
> > Why is that a problem?
>
> Because this loses the connection between the signal and its origin.
Not really, it doesn't. You get the same Lisp error you'd get in
Emacs proper.
> Because it imposes a cost which we may not want to pay.
What cost is that?
> The current "funcall" should be renamed to "safe_funcall", and a new
> "funcall" should be provided which does not catch signals.
I still think we should be pragmatic about that, not radical. If the
cake can be had and eaten, too, why not?
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 19:34 ` Eli Zaretskii
@ 2015-11-26 20:11 ` Stefan Monnier
2015-11-26 20:19 ` Eli Zaretskii
0 siblings, 1 reply; 59+ messages in thread
From: Stefan Monnier @ 2015-11-26 20:11 UTC (permalink / raw
To: Eli Zaretskii; +Cc: emacs-devel
>> Because this loses the connection between the signal and its origin.
> Not really, it doesn't. You get the same Lisp error you'd get in
> Emacs proper.
That's only the signal, not its origin. Its origin is lost.
>> Because it imposes a cost which we may not want to pay.
> What cost is that?
Catch and then rethrow. Which is pure cost with no benefit, if you ask me.
>> The current "funcall" should be renamed to "safe_funcall", and a new
>> "funcall" should be provided which does not catch signals.
> I still think we should be pragmatic about that, not radical.
That's exactly what I am. The straightforward code doesn't
catch&rethrow, so rather than let people do funcall_without_catch by
testing if the not_so_plain_funcall has caught a signal and then rethrow
it, it makes a boat load more sense to do it the other way around and
let those who need the signals to be caught to request explicitly the
not_so_plain_funcall.
> If the cake can be had and eaten, too, why not?
I'm fine with having both funcalls available. I just want to have the
"raw" funcall advertized at least as much as the other, and
the other one built on top rather than the other way around.
I actually find it difficult to believe I have to argue this point.
It's so blindingly obvious from a simple engineering perspective, not to
mention the decades of experience with using a "raw non-catching
funcall" from Emacs's C code.
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 20:11 ` Stefan Monnier
@ 2015-11-26 20:19 ` Eli Zaretskii
2015-11-26 21:20 ` Paul Eggert
2015-11-27 1:21 ` Stefan Monnier
0 siblings, 2 replies; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-26 20:19 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: emacs-devel@gnu.org
> Date: Thu, 26 Nov 2015 15:11:25 -0500
>
> >> Because this loses the connection between the signal and its origin.
> > Not really, it doesn't. You get the same Lisp error you'd get in
> > Emacs proper.
>
> That's only the signal, not its origin. Its origin is lost.
Not sure what you mean by that. The origin is clearly stated in the
error message.
> >> Because it imposes a cost which we may not want to pay.
> > What cost is that?
>
> Catch and then rethrow. Which is pure cost with no benefit, if you ask me.
A cost very close to zero. Let's keep the proper perspective.
> The straightforward code doesn't
> catch&rethrow, so rather than let people do funcall_without_catch by
> testing if the not_so_plain_funcall has caught a signal and then rethrow
> it, it makes a boat load more sense to do it the other way around and
> let those who need the signals to be caught to request explicitly the
> not_so_plain_funcall.
No one needs to do anything, the code is already written, and module
authors don't even need to know it exists, or what exactly does it do.
> > If the cake can be had and eaten, too, why not?
>
> I'm fine with having both funcalls available. I just want to have the
> "raw" funcall advertized at least as much as the other, and
> the other one built on top rather than the other way around.
Feel free to add it, then.
> I actually find it difficult to believe I have to argue this point.
> It's so blindingly obvious from a simple engineering perspective, not to
> mention the decades of experience with using a "raw non-catching
> funcall" from Emacs's C code.
It's not obvious to me, sorry. The costs of the current code are
minimal, and the advantages to have the "raw" functionality in
addition to what we have aren't clear-cut.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 20:19 ` Eli Zaretskii
@ 2015-11-26 21:20 ` Paul Eggert
2015-11-26 22:29 ` Philipp Stephani
2015-11-27 9:11 ` Eli Zaretskii
2015-11-27 1:21 ` Stefan Monnier
1 sibling, 2 replies; 59+ messages in thread
From: Paul Eggert @ 2015-11-26 21:20 UTC (permalink / raw
To: Eli Zaretskii, Stefan Monnier; +Cc: emacs-devel
Eli Zaretskii wrote:
> It's not obvious to me, sorry. The costs of the current code are
> minimal, and the advantages to have the "raw" functionality in
> addition to what we have aren't clear-cut.
My admittedly vague impression is that Stefan's approach would be friendlier to
module authors who want to write code that feels like Emacs's current C code.
This should be a plus, no?
I don't fully understand why the current emacs-module.c is as complicated as it
is, to be honest. I know it has something to do with C++ exception handling,
but the details still escape me. But really, we should support C modules well
too, as C is still the lingua franca for low-level software integration. And
"well" does not mean "every time you call a function you then have to call some
other function to see whether the first function worked".
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 21:20 ` Paul Eggert
@ 2015-11-26 22:29 ` Philipp Stephani
2015-11-26 22:33 ` Philipp Stephani
2015-11-27 1:06 ` Stefan Monnier
2015-11-27 9:11 ` Eli Zaretskii
1 sibling, 2 replies; 59+ messages in thread
From: Philipp Stephani @ 2015-11-26 22:29 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Stefan Monnier, Daniel Colascione
Cc: Emacs developers
[-- Attachment #1: Type: text/plain, Size: 1098 bytes --]
Paul Eggert <eggert@cs.ucla.edu> schrieb am Do., 26. Nov. 2015 um 22:21 Uhr:
> Eli Zaretskii wrote:
> > It's not obvious to me, sorry. The costs of the current code are
> > minimal, and the advantages to have the "raw" functionality in
> > addition to what we have aren't clear-cut.
>
> My admittedly vague impression is that Stefan's approach would be
> friendlier to
> module authors who want to write code that feels like Emacs's current C
> code.
> This should be a plus, no?
>
> I don't fully understand why the current emacs-module.c is as complicated
> as it
> is, to be honest. I know it has something to do with C++ exception
> handling,
> but the details still escape me. But really, we should support C modules
> well
> too, as C is still the lingua franca for low-level software integration.
> And
> "well" does not mean "every time you call a function you then have to call
> some
> other function to see whether the first function worked".
>
>
Please see Daniel's original design and the follow-up discussions:
https://lists.gnu.org/archive/html/emacs-devel/2015-02/msg00960.html
[-- Attachment #2: Type: text/html, Size: 1569 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 22:29 ` Philipp Stephani
@ 2015-11-26 22:33 ` Philipp Stephani
2015-11-27 1:06 ` Stefan Monnier
1 sibling, 0 replies; 59+ messages in thread
From: Philipp Stephani @ 2015-11-26 22:33 UTC (permalink / raw
To: Paul Eggert, Eli Zaretskii, Stefan Monnier, Daniel Colascione
Cc: Emacs developers
[-- Attachment #1: Type: text/plain, Size: 1337 bytes --]
Philipp Stephani <p.stephani2@gmail.com> schrieb am Do., 26. Nov. 2015 um
23:29 Uhr:
> Paul Eggert <eggert@cs.ucla.edu> schrieb am Do., 26. Nov. 2015 um
> 22:21 Uhr:
>
>> Eli Zaretskii wrote:
>> > It's not obvious to me, sorry. The costs of the current code are
>> > minimal, and the advantages to have the "raw" functionality in
>> > addition to what we have aren't clear-cut.
>>
>> My admittedly vague impression is that Stefan's approach would be
>> friendlier to
>> module authors who want to write code that feels like Emacs's current C
>> code.
>> This should be a plus, no?
>>
>> I don't fully understand why the current emacs-module.c is as complicated
>> as it
>> is, to be honest. I know it has something to do with C++ exception
>> handling,
>> but the details still escape me. But really, we should support C modules
>> well
>> too, as C is still the lingua franca for low-level software integration.
>> And
>> "well" does not mean "every time you call a function you then have to
>> call some
>> other function to see whether the first function worked".
>>
>>
> Please see Daniel's original design and the follow-up discussions:
> https://lists.gnu.org/archive/html/emacs-devel/2015-02/msg00960.html
>
Also this subthread with even more discussion:
https://lists.gnu.org/archive/html/emacs-devel/2015-09/msg00540.html
[-- Attachment #2: Type: text/html, Size: 2205 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 22:29 ` Philipp Stephani
2015-11-26 22:33 ` Philipp Stephani
@ 2015-11-27 1:06 ` Stefan Monnier
2015-11-27 1:10 ` Daniel Colascione
2015-11-27 8:12 ` Eli Zaretskii
1 sibling, 2 replies; 59+ messages in thread
From: Stefan Monnier @ 2015-11-27 1:06 UTC (permalink / raw
To: Philipp Stephani
Cc: Eli Zaretskii, Paul Eggert, Daniel Colascione, Emacs developers
> Please see Daniel's original design and the follow-up discussions:
The general design is good, but forcing this signal-handling is just
brain-dead from where I stand. I stated this many times. And I'm
shocked that we'd follow Daniel's design on this detail just because he
advocates it.
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 1:06 ` Stefan Monnier
@ 2015-11-27 1:10 ` Daniel Colascione
2015-11-27 15:06 ` Stefan Monnier
2015-11-27 8:12 ` Eli Zaretskii
1 sibling, 1 reply; 59+ messages in thread
From: Daniel Colascione @ 2015-11-27 1:10 UTC (permalink / raw
To: Stefan Monnier, Philipp Stephani
Cc: Eli Zaretskii, Paul Eggert, Emacs developers
[-- Attachment #1: Type: text/plain, Size: 617 bytes --]
On 11/26/2015 05:06 PM, Stefan Monnier wrote:
>> Please see Daniel's original design and the follow-up discussions:
>
> The general design is good, but forcing this signal-handling is just
> brain-dead from where I stand. I stated this many times. And I'm
> shocked that we'd follow Daniel's design on this detail just because he
> advocates it.
So we should follow your design because _you_ advocate it?
And it's not "just" because I advocate it --- there's a good reason that
the vast majority of general-purpose C libraries don't use non-local
control flow for general-purpose error reporting.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 20:19 ` Eli Zaretskii
2015-11-26 21:20 ` Paul Eggert
@ 2015-11-27 1:21 ` Stefan Monnier
2015-11-27 8:26 ` Eli Zaretskii
1 sibling, 1 reply; 59+ messages in thread
From: Stefan Monnier @ 2015-11-27 1:21 UTC (permalink / raw
To: Eli Zaretskii; +Cc: emacs-devel
>> >> Because this loses the connection between the signal and its origin.
>> > Not really, it doesn't. You get the same Lisp error you'd get in
>> > Emacs proper.
>> That's only the signal, not its origin. Its origin is lost.
> Not sure what you mean by that. The origin is clearly stated in the
> error message.
You mean debug-on-error will properly show me the right stack state and
let me look up and change the corresponding variables?
Hmm... didn't think so.
>> >> Because it imposes a cost which we may not want to pay.
>> > What cost is that?
>> Catch and then rethrow. Which is pure cost with no benefit, if you ask me.
> A cost very close to zero.
Who cares. Still pure cost with no benefit.
The core provides naturally a plain raw non-catching funcall, but with
the current design a module author who wants this behavior can't have it
because the module API hides it behind some "idiot-proofed layer", so
the best the module author can do is add yet another layer to try and
reproduce as best it can the underling non-catching funcall behavior.
This is completely dumb.
> No one needs to do anything, the code is already written, and module
> authors don't even need to know it exists, or what exactly does it do.
The criteria to accept bad design shouldn't be "does the code
already exist?".
> It's not obvious to me, sorry. The costs of the current code are
> minimal, and the advantages to have the "raw" functionality in
> addition to what we have aren't clear-cut.
As I said, we have plenty of experience in Emacs's own source code:
look in Emacs's source code and compare the number of uses of
"safe_call" and friends to the number of uses of "callN" and friends.
The catching version is useful at times, but it's the exception rather
than the rule. XEmacs's experience is the same, apparently.
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 1:06 ` Stefan Monnier
2015-11-27 1:10 ` Daniel Colascione
@ 2015-11-27 8:12 ` Eli Zaretskii
1 sibling, 0 replies; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-27 8:12 UTC (permalink / raw
To: Stefan Monnier; +Cc: p.stephani2, eggert, dancol, emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Thu, 26 Nov 2015 20:06:39 -0500
> Cc: Eli Zaretskii <eliz@gnu.org>, Paul Eggert <eggert@cs.ucla.edu>,
> Daniel Colascione <dancol@dancol.org>,
> Emacs developers <emacs-devel@gnu.org>
>
> > Please see Daniel's original design and the follow-up discussions:
>
> The general design is good, but forcing this signal-handling is just
> brain-dead from where I stand. I stated this many times. And I'm
> shocked that we'd follow Daniel's design on this detail just because he
> advocates it.
I think this is extreme and uncalled-for. You may disagree with the
design, but it's here and it works. It brings some additional
benefits, albeit not free of cost. After looking at the code for
quite some time, my conclusion is that the price is not insignificant,
but not painful enough to be an issue. It certainly doesn't deserve
to be called "brain-dead". Definitely not when the work has already
been done and endured the initial shock of being integrated with
Emacs.
So if you still disagree, let's please leave it at that, and move on.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 1:21 ` Stefan Monnier
@ 2015-11-27 8:26 ` Eli Zaretskii
2015-11-27 15:15 ` Stefan Monnier
0 siblings, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-27 8:26 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: emacs-devel@gnu.org
> Date: Thu, 26 Nov 2015 20:21:26 -0500
>
> >> >> Because this loses the connection between the signal and its origin.
> >> > Not really, it doesn't. You get the same Lisp error you'd get in
> >> > Emacs proper.
> >> That's only the signal, not its origin. Its origin is lost.
> > Not sure what you mean by that. The origin is clearly stated in the
> > error message.
>
> You mean debug-on-error will properly show me the right stack state and
> let me look up and change the corresponding variables?
Up to the C level, yes. You cannot do that once you get to the C
level, not with the Lisp debugger we have.
> Hmm... didn't think so.
Can you show some example of where some data is lost? Because I think
we may be miscommunicating: I don't see that significant lost of data
that causes such strenuous objections. Maybe you can explain that to
me. Maybe something is indeed missing.
> >> >> Because it imposes a cost which we may not want to pay.
> >> > What cost is that?
> >> Catch and then rethrow. Which is pure cost with no benefit, if you ask me.
> > A cost very close to zero.
>
> Who cares. Still pure cost with no benefit.
It's not without benefits.
> The core provides naturally a plain raw non-catching funcall, but with
> the current design a module author who wants this behavior can't have it
Why would a module author want a non-catching funcall? Are the
reasons for having that strong enough to override the dangers?
Because there are other things a module author currently cannot do, as
the API offers only limited ways into Emacs. Why would having a
non-catching funcall be so much more important than, say, being able
to add watchers to the Emacs event queue?
> This is completely dumb.
I'd appreciate if you refrained from name-calling. It doesn't help
keep the discussion technical and constructive.
> > No one needs to do anything, the code is already written, and module
> > authors don't even need to know it exists, or what exactly does it do.
>
> The criteria to accept bad design shouldn't be "does the code
> already exist?".
And whether it works, yes. This is Free Software: whoever does the
job gets to choose the tools and the methods. You know that.
> > It's not obvious to me, sorry. The costs of the current code are
> > minimal, and the advantages to have the "raw" functionality in
> > addition to what we have aren't clear-cut.
>
> As I said, we have plenty of experience in Emacs's own source code:
> look in Emacs's source code and compare the number of uses of
> "safe_call" and friends to the number of uses of "callN" and friends.
> The catching version is useful at times, but it's the exception rather
> than the rule. XEmacs's experience is the same, apparently.
Modules aren't core Emacs, and weren't supposed to be it. Not
everything that's possible in core _must_ be available to modules.
Modules aren't a way to extend Emacs in unlimited ways. So just
saying this is possible in core is not a useful argument in this
discussion. The important question here is: why is it important that
modules have this functionality at their disposal.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-26 21:20 ` Paul Eggert
2015-11-26 22:29 ` Philipp Stephani
@ 2015-11-27 9:11 ` Eli Zaretskii
2015-11-27 12:25 ` Aurélien Aptel
1 sibling, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-27 9:11 UTC (permalink / raw
To: Paul Eggert; +Cc: monnier, emacs-devel
> Cc: emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Thu, 26 Nov 2015 13:20:46 -0800
>
> Eli Zaretskii wrote:
> > It's not obvious to me, sorry. The costs of the current code are
> > minimal, and the advantages to have the "raw" functionality in
> > addition to what we have aren't clear-cut.
>
> My admittedly vague impression is that Stefan's approach would be friendlier to
> module authors who want to write code that feels like Emacs's current C code.
> This should be a plus, no?
Yes. I already posted a summary of the differences, and how IMO we
should go about keeping these differences to a minimum. No one
replied.
> I don't fully understand why the current emacs-module.c is as complicated as it
> is, to be honest. I know it has something to do with C++ exception handling,
> but the details still escape me. But really, we should support C modules well
> too, as C is still the lingua franca for low-level software integration. And
> "well" does not mean "every time you call a function you then have to call some
> other function to see whether the first function worked".
This is concealed in emacs-module.c. Module authors don't need to
know that, or be bothered. They can simply write code "as usual".
As to emacs-module.c, it's more complicated due to this, I agree. But
not too complicated, IMO. And the rules for writing functions in
emacs-module.c are really quite simple, they almost boil down to
having some pretty boilerplate code at the beginning of every
function. Maybe we even could come up with a single macro that
injects all that code.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 9:11 ` Eli Zaretskii
@ 2015-11-27 12:25 ` Aurélien Aptel
2015-11-27 14:44 ` Eli Zaretskii
2015-11-28 23:31 ` Paul Eggert
0 siblings, 2 replies; 59+ messages in thread
From: Aurélien Aptel @ 2015-11-27 12:25 UTC (permalink / raw
To: Eli Zaretskii; +Cc: Paul Eggert, Stefan Monnier, Emacs development discussions
As tedious as it sounds, checking for errors after every API call is
the safest way to go. We have to remind ourselves we're extending an
editor in C. Crashing/aborting can make someone loose work.
As ignorant as it will sound, working on the dynamic modules feature
made me realize how Emacs core might leak memory everytime a call
signals in the middle a function if you're not careful. I find this
very error-prone.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 12:25 ` Aurélien Aptel
@ 2015-11-27 14:44 ` Eli Zaretskii
2015-11-28 23:31 ` Paul Eggert
1 sibling, 0 replies; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-27 14:44 UTC (permalink / raw
To: Aurélien Aptel; +Cc: eggert, monnier, emacs-devel
> Date: Fri, 27 Nov 2015 13:25:26 +0100
> From: Aurélien Aptel <aurelien.aptel+emacs@gmail.com>
> Cc: Paul Eggert <eggert@cs.ucla.edu>, Stefan Monnier <monnier@iro.umontreal.ca>,
> Emacs development discussions <emacs-devel@gnu.org>
>
> As tedious as it sounds, checking for errors after every API call is
> the safest way to go.
With the latest emacs-25 branch, we no longer do. Which is a Good
Thing, IMO. Writing an Emacs module isn't supposed to be such an
unpleasant exercise.
> We have to remind ourselves we're extending an editor in
> C. Crashing/aborting can make someone loose work.
Who said anything about crashing? The current code doesn't crash, but
doesn't require error checking in the module code after each call to
an Emacs function. Please take a look.
Btw, if we are talking about crashing, I think the massive use of
eassert in emacs-module.c is a much more probable cause of losing work
than anything else. eassert is for things that "should never happen",
not for catching programmer's mistakes. An assertion that is violated
_really_ crashes Emacs and risks losing valuable work. Doing that
because some module has a bug is simply unacceptable.
> As ignorant as it will sound, working on the dynamic modules feature
> made me realize how Emacs core might leak memory everytime a call
> signals in the middle a function if you're not careful. I find this
> very error-prone.
You will have to explain that to us, because we do this in Emacs all
the time, and there are no leaks caused by that.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 1:10 ` Daniel Colascione
@ 2015-11-27 15:06 ` Stefan Monnier
0 siblings, 0 replies; 59+ messages in thread
From: Stefan Monnier @ 2015-11-27 15:06 UTC (permalink / raw
To: Daniel Colascione
Cc: Philipp Stephani, Paul Eggert, Eli Zaretskii, Emacs developers
>> The general design is good, but forcing this signal-handling is just
>> brain-dead from where I stand. I stated this many times. And I'm
>> shocked that we'd follow Daniel's design on this detail just because he
>> advocates it.
> So we should follow your design because _you_ advocate it?
Well, yes. All things being equal (i.e. just hot air on either side),
I'd assume that years-of-service and megabytes-of-contributions should
tilt the balance in my favor.
> And it's not "just" because I advocate it --- there's a good reason that
> the vast majority of general-purpose C libraries don't use non-local
> control flow for general-purpose error reporting.
Emacs is not a general purpose C library, so I don't see why that'd
be relevant.
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 8:26 ` Eli Zaretskii
@ 2015-11-27 15:15 ` Stefan Monnier
2015-11-27 15:57 ` Eli Zaretskii
0 siblings, 1 reply; 59+ messages in thread
From: Stefan Monnier @ 2015-11-27 15:15 UTC (permalink / raw
To: Eli Zaretskii; +Cc: emacs-devel
>> You mean debug-on-error will properly show me the right stack state and
>> let me look up and change the corresponding variables?
> Up to the C level, yes. You cannot do that once you get to the C
> level, not with the Lisp debugger we have.
So you're saying that if I call a command which internally calls
a C module function which turn does "env->funcall" on some Elisp code
which then signals an error, I'll be throw into the *Backtrace* buffer
(after setting debug-on-error and not debug-on-signal) right at the
point where the error is really signaled (i.e. before returning to the
module's C code), and not later on when it is rethrown by the module
code?
>> The core provides naturally a plain raw non-catching funcall, but with
>> the current design a module author who wants this behavior can't have it
> Why would a module author want a non-catching funcall?
Why not? Most funcalls from Emacs's C to Elisp in Emacs do not want to
catch errors and I see no reason why module code should be so
fundamentally different.
> Are the reasons for having that strong enough to override the dangers?
What danger?
> Because there are other things a module author currently cannot do, as
> the API offers only limited ways into Emacs.
Because it's less work than what the current code does. It's just
giving access to some internal entry point. Why hide this entry point?
>> The criteria to accept bad design shouldn't be "does the code
>> already exist?".
> And whether it works, yes.
No. These are necessary criteria but not sufficient.
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 15:15 ` Stefan Monnier
@ 2015-11-27 15:57 ` Eli Zaretskii
2015-11-27 16:29 ` Stefan Monnier
0 siblings, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-27 15:57 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: emacs-devel@gnu.org
> Date: Fri, 27 Nov 2015 10:15:49 -0500
>
> >> You mean debug-on-error will properly show me the right stack state and
> >> let me look up and change the corresponding variables?
> > Up to the C level, yes. You cannot do that once you get to the C
> > level, not with the Lisp debugger we have.
>
> So you're saying that if I call a command which internally calls
> a C module function which turn does "env->funcall" on some Elisp code
> which then signals an error, I'll be throw into the *Backtrace* buffer
> (after setting debug-on-error and not debug-on-signal) right at the
> point where the error is really signaled (i.e. before returning to the
> module's C code), and not later on when it is rethrown by the module
> code?
Yes:
emacs -Q
M-x load-file RET modules/mod-test/mod-test.dll
M-: (mod-test-string-a-to-b (string-match "a" nil) "b") RET
=>
Debugger entered--Lisp error: (wrong-type-argument stringp nil)
string-match("a" nil)
(mod-test-string-a-to-b (string-match "a" nil) "b")
eval((mod-test-string-a-to-b (string-match "a" nil) "b") nil)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
> >> The core provides naturally a plain raw non-catching funcall, but with
> >> the current design a module author who wants this behavior can't have it
> > Why would a module author want a non-catching funcall?
>
> Why not?
Sorry, "why not" is not an answer. If there's no real need for this
functionality, then there's no harm in not providing it.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 15:57 ` Eli Zaretskii
@ 2015-11-27 16:29 ` Stefan Monnier
2015-11-27 17:38 ` Eli Zaretskii
0 siblings, 1 reply; 59+ messages in thread
From: Stefan Monnier @ 2015-11-27 16:29 UTC (permalink / raw
To: Eli Zaretskii; +Cc: emacs-devel
>> So you're saying that if I call a command which internally calls
>> a C module function which turn does "env->funcall" on some Elisp code
>> which then signals an error, I'll be throw into the *Backtrace* buffer
>> (after setting debug-on-error and not debug-on-signal) right at the
>> point where the error is really signaled (i.e. before returning to the
>> module's C code), and not later on when it is rethrown by the module
>> code?
> Yes:
> emacs -Q
> M-x load-file RET modules/mod-test/mod-test.dll
> M-: (mod-test-string-a-to-b (string-match "a" nil) "b") RET
> =>
> Debugger entered--Lisp error: (wrong-type-argument stringp nil)
> string-match("a" nil)
> (mod-test-string-a-to-b (string-match "a" nil) "b")
> eval((mod-test-string-a-to-b (string-match "a" nil) "b") nil)
> elisp--eval-last-sexp(nil)
> eval-last-sexp(nil)
> funcall-interactively(eval-last-sexp nil)
> call-interactively(eval-last-sexp nil nil)
> command-execute(eval-last-sexp)
Hmm... that's not the case I'm talking about: here the string-match is
called before even entering the module's code, so the module code is not
involved at all.
>> >> The core provides naturally a plain raw non-catching funcall, but with
>> >> the current design a module author who wants this behavior can't have it
>> > Why would a module author want a non-catching funcall?
>> Why not?
> Sorry, "why not" is not an answer.
Given then 271-vs-15 rather of non-catching funcalls vs catching
funcalls in Emacs's C code, I think it's pretty clear that it can be
very useful. So really the question is the other way around: what makes
you think that the modules's code will be so vastly different that it
won't want a non-catching funcall, contrary to the experience so far?
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 16:29 ` Stefan Monnier
@ 2015-11-27 17:38 ` Eli Zaretskii
2015-11-27 17:54 ` Stefan Monnier
0 siblings, 1 reply; 59+ messages in thread
From: Eli Zaretskii @ 2015-11-27 17:38 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: emacs-devel@gnu.org
> Date: Fri, 27 Nov 2015 11:29:31 -0500
>
> > emacs -Q
> > M-x load-file RET modules/mod-test/mod-test.dll
> > M-: (mod-test-string-a-to-b (string-match "a" nil) "b") RET
> > =>
> > Debugger entered--Lisp error: (wrong-type-argument stringp nil)
> > string-match("a" nil)
> > (mod-test-string-a-to-b (string-match "a" nil) "b")
> > eval((mod-test-string-a-to-b (string-match "a" nil) "b") nil)
> > elisp--eval-last-sexp(nil)
> > eval-last-sexp(nil)
> > funcall-interactively(eval-last-sexp nil)
> > call-interactively(eval-last-sexp nil nil)
> > command-execute(eval-last-sexp)
>
> Hmm... that's not the case I'm talking about: here the string-match is
> called before even entering the module's code, so the module code is not
> involved at all.
Then maybe you could show the case you were talking about.
> >> >> The core provides naturally a plain raw non-catching funcall, but with
> >> >> the current design a module author who wants this behavior can't have it
> >> > Why would a module author want a non-catching funcall?
> >> Why not?
> > Sorry, "why not" is not an answer.
>
> Given then 271-vs-15 rather of non-catching funcalls vs catching
> funcalls in Emacs's C code, I think it's pretty clear that it can be
> very useful.
The count should be based on modules, not on what we have in core.
> So really the question is the other way around: what makes
> you think that the modules's code will be so vastly different that it
> won't want a non-catching funcall, contrary to the experience so far?
I think module authors won't (and shouldn't) care.
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 17:38 ` Eli Zaretskii
@ 2015-11-27 17:54 ` Stefan Monnier
0 siblings, 0 replies; 59+ messages in thread
From: Stefan Monnier @ 2015-11-27 17:54 UTC (permalink / raw
To: Eli Zaretskii; +Cc: emacs-devel
> Then maybe you could show the case you were talking about.
M-: (setq debug-on-error t) RET
M-: (mod-test-non-local-exit-funcall (lambda () (+ "" 2)))
Stefan
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: Dynamic modules: emacs-module.c and signaling errors
2015-11-27 12:25 ` Aurélien Aptel
2015-11-27 14:44 ` Eli Zaretskii
@ 2015-11-28 23:31 ` Paul Eggert
1 sibling, 0 replies; 59+ messages in thread
From: Paul Eggert @ 2015-11-28 23:31 UTC (permalink / raw
To: Aurélien Aptel, Eli Zaretskii
Cc: Stefan Monnier, Emacs development discussions
Aurélien Aptel wrote:
> working on the dynamic modules feature
> made me realize how Emacs core might leak memory everytime a call
> signals in the middle a function if you're not careful
If modules use the Emacs memory allocator we should be able to arrange for any
such leaks to be garbage collected, so this shouldn't be a problem.
^ permalink raw reply [flat|nested] 59+ messages in thread
end of thread, other threads:[~2015-11-28 23:31 UTC | newest]
Thread overview: 59+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-24 19:41 Dynamic modules: emacs-module.c and signaling errors Eli Zaretskii
2015-11-24 19:45 ` Eli Zaretskii
2015-11-24 20:12 ` Tom Tromey
2015-11-24 20:49 ` Eli Zaretskii
2015-11-24 21:34 ` Paul Eggert
2015-11-24 21:55 ` Daniel Colascione
2015-11-25 6:52 ` Paul Eggert
2015-11-25 7:03 ` Daniel Colascione
2015-11-25 7:14 ` Paul Eggert
2015-11-25 7:18 ` Daniel Colascione
2015-11-25 7:23 ` Paul Eggert
2015-11-25 7:25 ` Daniel Colascione
2015-11-25 7:49 ` Paul Eggert
2015-11-25 7:52 ` Daniel Colascione
2015-11-25 7:58 ` Paul Eggert
2015-11-25 8:12 ` Daniel Colascione
2015-11-25 8:24 ` Paul Eggert
2015-11-25 8:50 ` Daniel Colascione
2015-11-25 9:11 ` Daniel Colascione
2015-11-25 18:19 ` Eli Zaretskii
2015-11-25 18:26 ` Philipp Stephani
2015-11-25 19:19 ` Eli Zaretskii
2015-11-25 21:52 ` Philipp Stephani
2015-11-25 17:34 ` Paul Eggert
2015-11-24 22:21 ` Tom Tromey
2015-11-25 6:55 ` Paul Eggert
2015-11-25 17:30 ` Eli Zaretskii
2015-11-25 17:34 ` Paul Eggert
2015-11-25 21:23 ` Stefan Monnier
2015-11-26 15:42 ` Eli Zaretskii
2015-11-26 16:36 ` Stefan Monnier
2015-11-26 17:08 ` Eli Zaretskii
2015-11-26 19:28 ` Stefan Monnier
2015-11-26 19:34 ` Eli Zaretskii
2015-11-26 20:11 ` Stefan Monnier
2015-11-26 20:19 ` Eli Zaretskii
2015-11-26 21:20 ` Paul Eggert
2015-11-26 22:29 ` Philipp Stephani
2015-11-26 22:33 ` Philipp Stephani
2015-11-27 1:06 ` Stefan Monnier
2015-11-27 1:10 ` Daniel Colascione
2015-11-27 15:06 ` Stefan Monnier
2015-11-27 8:12 ` Eli Zaretskii
2015-11-27 9:11 ` Eli Zaretskii
2015-11-27 12:25 ` Aurélien Aptel
2015-11-27 14:44 ` Eli Zaretskii
2015-11-28 23:31 ` Paul Eggert
2015-11-27 1:21 ` Stefan Monnier
2015-11-27 8:26 ` Eli Zaretskii
2015-11-27 15:15 ` Stefan Monnier
2015-11-27 15:57 ` Eli Zaretskii
2015-11-27 16:29 ` Stefan Monnier
2015-11-27 17:38 ` Eli Zaretskii
2015-11-27 17:54 ` Stefan Monnier
2015-11-25 18:10 ` Tom Tromey
2015-11-25 18:15 ` Eli Zaretskii
2015-11-25 18:09 ` Philipp Stephani
2015-11-25 21:19 ` Stefan Monnier
2015-11-26 15:41 ` Eli Zaretskii
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.