From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Philipp Stephani Newsgroups: gmane.emacs.devel Subject: Re: Dynamic modules: emacs-module.c and signaling errors Date: Wed, 25 Nov 2015 18:09:25 +0000 Message-ID: References: <83k2p7xk13.fsf@gnu.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=089e0102def4565de10525615cc6 X-Trace: ger.gmane.org 1448474990 31915 80.91.229.3 (25 Nov 2015 18:09:50 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 25 Nov 2015 18:09:50 +0000 (UTC) Cc: emacs-devel@gnu.org To: Eli Zaretskii , aurelien.aptel+emacs@gmail.com, tzz@lifelogs.com, dancol@dancol.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Nov 25 19:09:48 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1a1eVj-0002oM-CK for ged-emacs-devel@m.gmane.org; Wed, 25 Nov 2015 19:09:43 +0100 Original-Received: from localhost ([::1]:47015 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a1eVl-0006oN-5G for ged-emacs-devel@m.gmane.org; Wed, 25 Nov 2015 13:09:45 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:33806) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a1eVf-0006jq-4k for emacs-devel@gnu.org; Wed, 25 Nov 2015 13:09:40 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a1eVd-0004YW-Uq for emacs-devel@gnu.org; Wed, 25 Nov 2015 13:09:39 -0500 Original-Received: from mail-wm0-x235.google.com ([2a00:1450:400c:c09::235]:37298) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a1eVb-0004Vk-Mo; Wed, 25 Nov 2015 13:09:35 -0500 Original-Received: by wmww144 with SMTP id w144so80100032wmw.0; Wed, 25 Nov 2015 10:09:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-type; bh=Bauxtxfgd+xzKH7SiA4T1sEyHL0AUQwfGBUHB4ieGAA=; b=e2XycFMCboV28SMtFCMgfJ++jgnre9q0S3RVQX2/jgxk0GX+Amk9ekWUlqBWvWkZj+ x+hEv3Vh7B4AIEYzorunKPPmP+tMOtMK0C9/fow5nEGoNLDuHyaxXAr5wyiUfuj7+7y4 fuxyzhmNAPbKFW2i1zLOcEXWlSbd7IUPUcCV6HrEdFl2QtZ5Y4n1ZAkIZ1nyFpArcq+4 M2nupetErvADFepUAO4Nm4gNrt/NE6UlaynyDPRzisfY5kfbhdKNlYvQygTDE/usInv9 s7YrW2Xq1iTnicezPCv3YvgXLgC0b3TcMNzSPCpjF6eHKrHNtwYLiPFVG9f4rPUA34Qc J6aw== X-Received: by 10.194.87.39 with SMTP id u7mr44901076wjz.11.1448474974770; Wed, 25 Nov 2015 10:09:34 -0800 (PST) In-Reply-To: <83k2p7xk13.fsf@gnu.org> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:400c:c09::235 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:195234 Archived-At: --089e0102def4565de10525615cc6 Content-Type: text/plain; charset=UTF-8 Eli Zaretskii 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? --089e0102def4565de10525615cc6 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable


Eli Za= retskii <eliz@gnu.org> schrieb am= Di., 24. Nov. 2015 um 20:41=C2=A0Uhr:
In "emacs -Q", load the modules/mod-test/mod-test module, the= n try
this:

=C2=A0 M-: (mod-test-sum "1" 2) RET

Result: Emacs aborts.=C2=A0 This happens because the eassert in
module_extract_integer aborts, when that function is called for the
2nd time:

=C2=A0 static intmax_t
=C2=A0 module_extract_integer (emacs_env *env, emacs_value n)
=C2=A0 {
=C2=A0 =C2=A0 check_main_thread ();
=C2=A0 =C2=A0 eassert (module_non_local_exit_check (env) =3D=3D emacs_funca= ll_exit_return);
=C2=A0 =C2=A0 Lisp_Object l =3D value_to_lisp (n);
=C2=A0 =C2=A0 if (! INTEGERP (l))
=C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 module_wrong_type (env, Qintegerp, l);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return 0;
=C2=A0 =C2=A0 =C2=A0 }

The first call to module_extract_integer correctly detects the wrong
type of argument and calls module_wrong_type.=C2=A0 But module_wrong_type just records the problem in the env structure, it doesn't signal any Lisp error, like an Emacs primitive would.=C2=A0 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 exampl= e module (unfortunately that was written before the error handling got impl= emented), but the gist is that functions returning emacs_value should usual= ly be called like this:

emacs_value ret =3D env-&g= t;foo(env, ...);
if (ret =3D=3D 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:

__att= ribute__((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_valu= e ret;
if (!env->foo(env, ..., &ret)) return false;
<= div>
which isn't worse, but avoids sentinel values and ma= kes the API harder to misuse. Thoughts?
--089e0102def4565de10525615cc6--