1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-13 17:20:21 +02:00

Update the thread stack base when `scm_with_guile' is invoked multiple times.

* NEWS: Update.

* libguile/threads.c (scm_i_init_thread_for_guile): When the thread is
  already guilified, update `t->base' so that it corresponds to the new
  stack base.  Bug report and patch by Linas Vepstas <linasvepstas@gmail.com>.

* test-suite/standalone/Makefile.am (test_scm_with_guile_CFLAGS,
  test_scm_with_guile_LDADD): New.
  (check_PROGRAMS, TESTS): Add `test-scm-with-guile'.
This commit is contained in:
Ludovic Courtès 2008-11-14 00:35:32 +01:00
parent b578508acd
commit cd1a1e47b5
5 changed files with 88 additions and 5 deletions

2
NEWS
View file

@ -41,6 +41,8 @@ available: Guile is now always configured in "maintainer mode".
** Fix build failure on Debian hppa architecture (bad stack growth detection)
** Fix `gcd' when called with a single, negative argument.
** Fix `Stack overflow' errors seen when building on some platforms
** Fix bug when `scm_with_guile ()' was called several times from the
same thread
Changes in 1.8.5 (since 1.8.4)

View file

@ -593,10 +593,19 @@ scm_i_init_thread_for_guile (SCM_STACKITEM *base, SCM parent)
{
/* This thread is already guilified but not in guile mode, just
resume it.
XXX - base might be lower than when this thread was first
guilified.
*/
A user call to scm_with_guile() will lead us to here. This could
happen from anywhere on the stack, and in particular lower on the
stack than when it was when this thread was first guilified. Thus,
`base' must be updated. */
#if SCM_STACK_GROWS_UP
if (base < t->base)
t->base = base;
#else
if (base > t->base)
t->base = base;
#endif
scm_enter_guile ((scm_t_guile_ticket) t);
return 1;
}

View file

@ -6,3 +6,4 @@
/test-unwind
/test-with-guile-module
/test-use-srfi
/test-scm-with-guile

View file

@ -121,9 +121,14 @@ test_with_guile_module_LDADD = ${top_builddir}/libguile/libguile.la
check_PROGRAMS += test-with-guile-module
TESTS += test-with-guile-module
test_scm_with_guile_CFLAGS = ${test_cflags}
test_scm_with_guile_LDADD = ${top_builddir}/libguile/libguile.la
check_PROGRAMS += test-scm-with-guile
TESTS += test-scm-with-guile
else
EXTRA_DIST += test-with-guile-module.c
EXTRA_DIST += test-with-guile-module.c test-scm-with-guile.c
endif

View file

@ -0,0 +1,66 @@
/* Copyright (C) 2008 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Test whether `scm_with_guile ()' can be called several times from a given
thread, but from a different stack depth. Up to 1.8.5, `scm_with_guile
()' would not update the thread's `base' field, which would then confuse
the GC.
See http://lists.gnu.org/archive/html/guile-devel/2008-11/msg00037.html
for a detailed report. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <libguile.h>
static void *
entry_point (void *arg)
{
/* Invoke the GC. If `THREAD->base' is incorrect, then Guile will just
segfault somewhere in `scm_mark_locations ()'. */
scm_gc ();
return NULL;
}
static void
go_deeper_into_the_stack (unsigned level)
{
/* The assumption is that the compiler is not smart enough to optimize this
out. */
if (level > 0)
go_deeper_into_the_stack (level - 1);
else
scm_with_guile (entry_point, NULL);
}
int
main (int argc, char *argv[])
{
/* Invoke `scm_with_guile ()' from someplace deep into the stack. */
go_deeper_into_the_stack (100);
/* Invoke it from much higher into the stack. This time, Guile is expected
to update the `base' field of the current thread. */
scm_with_guile (entry_point, NULL);
return 0;
}