unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Exception-safety for C++ code integrated with Guile.
@ 2015-02-23 21:59 Taahir Ahmed
  2015-02-24 18:52 ` Eli Zaretskii
  2015-03-10 21:15 ` Andy Wingo
  0 siblings, 2 replies; 6+ messages in thread
From: Taahir Ahmed @ 2015-02-23 21:59 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 2453 bytes --]

Over the past few days, I've been working on reducing the amount of
defensive coding that is required when writing Guile extensions using
C++.

My primary goal is to ensure that destructors of automatic variables
are called if any Guile non-local control flow passes through a C++
stack frame.

I'm writing to the list for three purposes:

  1) To check that I'm not duplicating any other ongoing work,

  2) To float two different implementation strategies and see which
     one is the best choice going forward, and

  3) To get clarification on some issues that I've encountered with a
     prototype implementation.

The two major strategies I considered are:

  1) Replace all uses of set/longjmp in the Guile source with C++
     exceptions.  This approach is simple in some ways, and
     complicated in others.  I would hesitate to pursue this unless
     Guile has some sort of longer-term plan to move towards C++.

  2) Replace all uses of set/longjmp with replacements (call them
     eh_setjmp and eh_longjmp) that are based on libunwind [1].
     eh_longjmp uses libunwind to walk up the stack, calling each
     frame's personality routine [2].  This approach will requires a
     platform that uses DWARF exception handling (i.e., everybody
     except non-Cygwin Windows).  It has the potential to make calls
     to setjmp much faster, but calls to longjmp would take linear (as
     opposed to constant) time in the number of stack frames crossed.

I've started working on a proof-of-concept for option 2 (heavily
cribbed from libunwind's own set/longjmp replacement).

However, I've run into an issue --- many of Guile's uses of setjmp
don't conform to the C standard.  In particular, after experiencing a
non-local return from setjmp, you're not allowed to access any
non-volatile local variables, but Guile does (see the local variable
mx in eval()).

In effect, Guile is assuming that setjmp saves and restores registers,
but the standard doesn't require that behavior from setjmp.  I can
make my setjmp implementation save all registers, but I decided to
first check and see if this was a conscious decision to embrace
nonportability, or an accidental one.

Thanks,

Taahir Ahmed

----------------------------------------------------------------------

[1] http://www.nongnu.org/libunwind/index.html
[2] http://mentorembedded.github.io/cxx-abi/abi-eh.html#base-personality

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Exception-safety for C++ code integrated with Guile.
  2015-02-23 21:59 Exception-safety for C++ code integrated with Guile Taahir Ahmed
@ 2015-02-24 18:52 ` Eli Zaretskii
  2015-02-24 19:21   ` Taahir Ahmed
  2015-02-24 19:59   ` Taahir Ahmed
  2015-03-10 21:15 ` Andy Wingo
  1 sibling, 2 replies; 6+ messages in thread
From: Eli Zaretskii @ 2015-02-24 18:52 UTC (permalink / raw)
  To: ahmed.taahir; +Cc: guile-devel

> From: Taahir Ahmed <ahmed.taahir@gmail.com>
> Date: Mon, 23 Feb 2015 15:59:43 -0600
> 
>   2) Replace all uses of set/longjmp with replacements (call them
>      eh_setjmp and eh_longjmp) that are based on libunwind [1].
>      eh_longjmp uses libunwind to walk up the stack, calling each
>      frame's personality routine [2].  This approach will requires a
>      platform that uses DWARF exception handling (i.e., everybody
>      except non-Cygwin Windows).

mingw.org's MinGW uses DWARF exception handling.  Perhaps you are
thinking of MinGW64, which (AFAIK) indeed uses eh by default, but can
be configured to use DWARF.

As for libunwind, are you sure it supports enough platforms to be a
useful alternative?  AFAIK, the last official release supports only
IA-64, and even the current development version in git repo basically
supports GNU/Linux and almost nothing else (2 FreeBSD targets and 1 on
HP-UX).



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Exception-safety for C++ code integrated with Guile.
  2015-02-24 18:52 ` Eli Zaretskii
@ 2015-02-24 19:21   ` Taahir Ahmed
  2015-02-24 19:36     ` Eli Zaretskii
  2015-02-24 19:59   ` Taahir Ahmed
  1 sibling, 1 reply; 6+ messages in thread
From: Taahir Ahmed @ 2015-02-24 19:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 1725 bytes --]

> mingw.org's MinGW uses DWARF exception handling.  Perhaps you are
> thinking of MinGW64, which (AFAIK) indeed uses eh by default, but can
> be configured to use DWARF.

I was under the impression that MinGW only used setjump/longjump exception 
handling, with plans to move to Windows SEH.  Either way, it's neither here 
nor there.

> As for libunwind, are you sure it supports enough platforms to be a
> useful alternative?  AFAIK, the last official release supports only
> IA-64, and even the current development version in git repo basically
> supports GNU/Linux and almost nothing else (2 FreeBSD targets and 1 on
> HP-UX).

The documentation of the last official release (v1.1, in 2012) only mentions 
ia64, but it appears to actually support the same list of platforms as the 
current version.

From looking at the libunwind source, the only os-dependent code is a single 
function for looking through an elf image.  The rest of the code is written 
once for each architecture (more specifically, once for each 
architecture/calling convention tuple).

What are the platforms that Guile supports? (I can't find a comprehensive list 
anywhere).  In _scm.h, I can see special casing of sj/lj for vms, cray(!!), 
and ia64.  There's no need to change the behavior for vms and cray.  The ia64 
special casing is simply to force all registers to be saved, which is easy to 
handle.  It seems reasonable that all other cases will be covered by libunwind 
(or at least, libunwind with some small modifications).

Of course, if testing uncovers an os/arch tuple that doesn't work, one can 
simply fall back to the standard system sj/lj, and not having C++ cleanup 
behavior on those platforms.

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Exception-safety for C++ code integrated with Guile.
  2015-02-24 19:21   ` Taahir Ahmed
@ 2015-02-24 19:36     ` Eli Zaretskii
  0 siblings, 0 replies; 6+ messages in thread
From: Eli Zaretskii @ 2015-02-24 19:36 UTC (permalink / raw)
  To: ahmed.taahir; +Cc: guile-devel

> From: Taahir Ahmed <ahmed.taahir@gmail.com>
> Cc: guile-devel@gnu.org
> Date: Tue, 24 Feb 2015 13:21:48 -0600
> 
> From looking at the libunwind source, the only os-dependent code is a single 
> function for looking through an elf image.

So it's only good for platforms that use ELF?  If so, none of Windows
GNU-based environments will do, they all use PE-COFF.

> What are the platforms that Guile supports? (I can't find a comprehensive list 
> anywhere).

That's a good question, I hope that people here will know the answer
(I don't, sorry).



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Exception-safety for C++ code integrated with Guile.
  2015-02-24 18:52 ` Eli Zaretskii
  2015-02-24 19:21   ` Taahir Ahmed
@ 2015-02-24 19:59   ` Taahir Ahmed
  1 sibling, 0 replies; 6+ messages in thread
From: Taahir Ahmed @ 2015-02-24 19:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 440 bytes --]

Alternatively, it looks like both gcc and clang export the ia64 c++ exception 
api as <unwind.h>.  (Note that it is called "ia64" as a historical artifact, 
since it was originally developed for ia64).

It looks like it should be easy to have some sj/lj wrappers that use the 
system sj/lj for register saving and jumping, and the <unwind.h> interface to 
destroy intermediate frames.

I'll try to hack up a solution based on this.

Taahir

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Exception-safety for C++ code integrated with Guile.
  2015-02-23 21:59 Exception-safety for C++ code integrated with Guile Taahir Ahmed
  2015-02-24 18:52 ` Eli Zaretskii
@ 2015-03-10 21:15 ` Andy Wingo
  1 sibling, 0 replies; 6+ messages in thread
From: Andy Wingo @ 2015-03-10 21:15 UTC (permalink / raw)
  To: Taahir Ahmed; +Cc: guile-devel

Hi Taahir,

On Mon 23 Feb 2015 22:59, Taahir Ahmed <ahmed.taahir@gmail.com> writes:

> Over the past few days, I've been working on reducing the amount of
> defensive coding that is required when writing Guile extensions using
> C++.
>
> My primary goal is to ensure that destructors of automatic variables
> are called if any Guile non-local control flow passes through a C++
> stack frame.

I was thinking about this recently too, in the context of GDB's upcoming
switch to C++, though I didn't get very far in the thinking.

>   1) To check that I'm not duplicating any other ongoing work,

Not that I know of.  Doesn't matter anyway, a good solution is always
acceptable :)

>   2) To float two different implementation strategies and see which
>      one is the best choice going forward, and
>
>   3) To get clarification on some issues that I've encountered with a
>      prototype implementation.

Cool.

> The two major strategies I considered are:
>
>   1) Replace all uses of set/longjmp in the Guile source with C++
>      exceptions.  This approach is simple in some ways, and
>      complicated in others.  I would hesitate to pursue this unless
>      Guile has some sort of longer-term plan to move towards C++.

I am not C++-averse but a hypothetical move towards C++ in a Guile
context doesn't necessarily mean moving towards use of exceptions.
Scheme has fairly complicated control flow and embracing C++ exceptions
doesn't necessarily solve things.  For example an exception propagating
over natively-compiled Scheme code would have to run dynwinds.  Calling
out to C++ would have to set up some sort of try/catch.  Is that the
right design?  I don't know.

(I do think that the C-stack-saving aspect of Guile's continuations is a
silly thing, given that delimited continuations are more expressive, we
can have escape-only continuations either way, and our VM and future
native compilation pipeline means that we don't have so much rewinding
of C stack frames, and in any case rewinding is unexpected and untested
by most Guile core code, not to mention user code.)

>   2) Replace all uses of set/longjmp with replacements (call them
>      eh_setjmp and eh_longjmp) that are based on libunwind [1].

No opinion other than a vague aversion to dependencies.

> However, I've run into an issue --- many of Guile's uses of setjmp
> don't conform to the C standard.  In particular, after experiencing a
> non-local return from setjmp, you're not allowed to access any
> non-volatile local variables, but Guile does (see the local variable
> mx in eval()).

You are allowed to access variables that could never be assigned after
the setjmp, AFAIK?  Anyway how is mx accessed before being re-set after
a prompt longjmp?

Cheers, and thanks for looking at this,

Andy
-- 
http://wingolog.org/



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-03-10 21:15 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-23 21:59 Exception-safety for C++ code integrated with Guile Taahir Ahmed
2015-02-24 18:52 ` Eli Zaretskii
2015-02-24 19:21   ` Taahir Ahmed
2015-02-24 19:36     ` Eli Zaretskii
2015-02-24 19:59   ` Taahir Ahmed
2015-03-10 21:15 ` Andy Wingo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).