unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
* bug#13611: SEGV during SMOB GC
@ 2013-02-02 20:51 Mike Gran
  2013-02-05 10:07 ` Ludovic Courtès
  0 siblings, 1 reply; 9+ messages in thread
From: Mike Gran @ 2013-02-02 20:51 UTC (permalink / raw)
  To: 13611

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

Hello-

I have a reproducible SEGV during GC of SMOBs on Guile 2.0.7.
It was also present in 2.0.6.


To reproduce compile main.c as 

$ gcc -std=gnu99 -shared -o smobbug.so -Wall -Wextra `pkg-config guile-2.0 --cflags --libs` -fPIC main.c


Then with
$ LD_PRELOAD=./smobbug.so LD_LIBRARY_PATH=. GUILE_LOAD_PATH=. guile

;; At the repl, load the lib

 (use-modules (smobbug))
;; Make a SMOB to be GC'd

 (handlesmob-init)
;; Trigger a GC from the GC thread
 (string-length (make-string 10000000))

This gives

  Program received signal SIGSEGV, Segmentation fault.
  [Switching to Thread 0xb7d98b40 (LWP 20488)]
  0xb7f251ab in smob_mark (addr=0x8608ff0, mark_stack_ptr=0xb7d90308, 
      mark_stack_limit=0xb7d982f0, env=0) at smob.c:325
  325           SCM_I_CURRENT_THREAD->current_mark_stack_ptr = mark_stack_ptr;

Here's what's happening internally.  When Guile starts up, it creates 3
threads
* Initial thread
* GC thread from scm_storage_prehistory GC_INIT()
* signal delivery thread

That second thread is the one from which automatic garbage collection
occurs.  The way that thread gets created, it has an
scm_i_current_thread == NULL, apparently.


So dereferencing scm_i_current_thread causes null dereference.
And smob_mark() will dereference scm_i_current_thread when collecting a
smob with a mark function.

-Mike

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: smobbug.scm --]
[-- Type: text/x-scheme; name="smobbug.scm", Size: 174 bytes --]

(define-module (smobbug)
  #:export ( 
	    handlesmob-init
	    ))

(load-extension "smobbug" "smobbug_init")

(define (handlesmob-init)
  "docstring"
  (%handlesmob-init))

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: main.c --]
[-- Type: text/x-csrc; name="main.c", Size: 1389 bytes --]

#define _GNU_SOURCE
#include <stdio.h>
#include <libguile.h>

static scm_t_bits handlesmob_tag;
void smobbug_init (void);
SCM mark_handle (SCM x);


SCM handlesmob_init ()
{
  SCM s_handlesmob;
  char *handle;

  handle = malloc (1);
  
  return SCM_NEWSMOB (s_handlesmob, handlesmob_tag, handle);
}

SCM
mark_handlesmob (SCM x)
{
  // No SCMs in the handle type: nothing to do here.
  return (SCM_BOOL_F);
}

size_t
free_handlesmob (SCM handle)
{
  SCM_ASSERT (SCM_SMOB_PREDICATE (handlesmob_tag, handle), handle, SCM_ARG1, "free-handlesmob");

  char *m = SCM_SMOB_DATA (handle);

  if (m != NULL)
      free (m);

  return 0;
}

int
print_handlesmob (SCM x, SCM port, scm_print_state *pstate)
{
  char *frm = (char *) SCM_SMOB_DATA (x);
  char *str;

  scm_puts ("#<handlesmob ", port);

  if (frm == (char *) NULL)
    {
      scm_puts ("(freed)", port);
    }
  else
    {
      if (asprintf (&str, "%p", frm) < 0)
	scm_puts ("???", port);
      else
	scm_puts (str, port);
    }

  scm_puts (">", port);
  
  // non-zero means success 
  return 1;
}

void
smobbug_init ()
{
  handlesmob_tag = scm_make_smob_type ("handlesmob", sizeof (char *));
  scm_set_smob_mark (handlesmob_tag, mark_handlesmob);
  scm_set_smob_free (handlesmob_tag, free_handlesmob);
  scm_set_smob_print (handlesmob_tag, print_handlesmob);
  scm_c_define_gsubr ("%handlesmob-init", 0, 0, 0, handlesmob_init);
}

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

* bug#13611: SEGV during SMOB GC
  2013-02-02 20:51 bug#13611: SEGV during SMOB GC Mike Gran
@ 2013-02-05 10:07 ` Ludovic Courtès
  2013-02-05 16:29   ` Mike Gran
  0 siblings, 1 reply; 9+ messages in thread
From: Ludovic Courtès @ 2013-02-05 10:07 UTC (permalink / raw)
  To: Mike Gran; +Cc: 13611

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

Hi Mike,

Mike Gran <spk121@yahoo.com> skribis:

> This gives
>
>   Program received signal SIGSEGV, Segmentation fault.
>   [Switching to Thread 0xb7d98b40 (LWP 20488)]
>   0xb7f251ab in smob_mark (addr=0x8608ff0, mark_stack_ptr=0xb7d90308, 
>       mark_stack_limit=0xb7d982f0, env=0) at smob.c:325
>   325           SCM_I_CURRENT_THREAD->current_mark_stack_ptr = mark_stack_ptr;
>
> Here's what's happening internally.  When Guile starts up, it creates 3
> threads
> * Initial thread
> * GC thread from scm_storage_prehistory GC_INIT()
> * signal delivery thread
>
> That second thread is the one from which automatic garbage collection
> occurs.  The way that thread gets created, it has an
> scm_i_current_thread == NULL, apparently.

Is there any chance that you’re using a GC 7.3 pre-release?

There was a similar report on IRC, and the fix appears to be:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 716 bytes --]

--- a/libguile/smob.c
+++ b/libguile/smob.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004, 2006, 2009, 2010, 2011, 2012, 2013 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
@@ -318,7 +318,7 @@ smob_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
 				     mark_stack_ptr,
 				     mark_stack_limit, NULL);
 
-  if (scm_smobs[smobnum].mark)
+  if (scm_smobs[smobnum].mark && SCM_I_CURRENT_THREAD != NULL)
     {
       SCM obj;
 

[-- Attachment #3: Type: text/plain, Size: 72 bytes --]


(Note that on 2.0 SMOB mark procedures are unnecessary.)

Ludo’.

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

* bug#13611: SEGV during SMOB GC
  2013-02-05 10:07 ` Ludovic Courtès
@ 2013-02-05 16:29   ` Mike Gran
  2013-02-05 16:41     ` Ludovic Courtès
  0 siblings, 1 reply; 9+ messages in thread
From: Mike Gran @ 2013-02-05 16:29 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 13611@debbugs.gnu.org

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

> From: Ludovic Courtès <ludo@gnu.org>

> Is there any chance that you’re using a GC 7.3 pre-release?

Using gc-7.2b-2.fc17.i686
on Linux 3.6.10-2.fc17.i686 #1 SMP 

> There was a similar report on IRC, and the fix appears to be:

It does fix my SEGV

> (Note that on 2.0 SMOB mark procedures are unnecessary.)

Cool.  Let's yank it from the manual.  Case closed.

Yet...

For what it is worth, I decided to get som statistics on how
often smob_mark is called from a thread with scm_i_current_thread
== NULL vs how often it is called from a thread where it is 
not null.

I wrote the attached patch, and then, using the same little
library as in my initial report, I ran

 (use-modules (smobbug))
 ;; Create a SMOB type
 (handlesmob-init)
 (for-each (lambda (x) (gc))
       (iota 1000))
 (gc-smob-mark-report)

This returned

 Count of GC SMOB marks from null thread: 176
 Count of GC SMOB marks from current thread: 825

Is that expected that GC is sometimes called from a 
thread where scm_i_current_thread is null and sometimes
called from a thread where scm_i_current_thread is
not null?

-Mike 

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: smob_gc_mark_report.patch --]
[-- Type: text/x-patch; name="smob_gc_mark_report.patch", Size: 3183 bytes --]

From 807b00d91fa3b7016987ecfd6992e7b7e943d1e3 Mon Sep 17 00:00:00 2001
From: Mike Gran <spk121@yahoo.com>
Date: Tue, 5 Feb 2013 08:18:07 -0800
Subject: [PATCH] Add function to debug smob gc

* libguile/gc.c (scm_gc_smob_mark_report): new report function
* libguile/gc.h: new declaration of scm_gc_smob_mark_report
* libguile/smob.c (smob_mark): gather statistics
---
 libguile/gc.c   | 22 ++++++++++++++++++++++
 libguile/gc.h   |  1 +
 libguile/smob.c |  8 +++++++-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/libguile/gc.c b/libguile/gc.c
index 06b5044..d06fa6c 100644
--- a/libguile/gc.c
+++ b/libguile/gc.c
@@ -77,6 +77,10 @@ extern unsigned long * __libc_ia64_register_backing_store_base;
 int scm_debug_cell_accesses_p = 0;
 int scm_expensive_debug_cell_accesses_p = 0;
 
+
+extern long scm_mark_from_null;
+extern long scm_mark_from_current;
+
 /* Set this to 0 if no additional gc's shall be performed, otherwise set it to
  * the number of cell accesses after which a gc shall be called.
  */
@@ -383,6 +387,24 @@ SCM_DEFINE (scm_gc_enable, "gc-enable", 0, 0, 0,
 }
 #undef FUNC_NAME
 
+SCM_DEFINE (scm_gc_smob_mark_report, "gc-smob-mark-report", 0, 0, 0,
+	    (),
+	    "Print statistics on gc marking of smobs.")
+#define FUNC_NAME s_scm_gc_smob_mark_report
+{
+  scm_puts ("Count of GC SMOB marks from null thread: ",
+	    scm_current_output_port ());
+  scm_display (scm_from_long (scm_mark_from_null), scm_current_output_port ());
+  scm_newline (scm_current_output_port ());
+  scm_puts ("Count of GC SMOB marks from current thread: ",
+	    scm_current_output_port ());
+  scm_display (scm_from_long (scm_mark_from_current),
+	       scm_current_output_port ());
+  scm_newline (scm_current_output_port ());
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
 
 SCM_DEFINE (scm_gc, "gc", 0, 0, 0,
            (),
diff --git a/libguile/gc.h b/libguile/gc.h
index 9f00e01..1120aa8 100644
--- a/libguile/gc.h
+++ b/libguile/gc.h
@@ -173,6 +173,7 @@ SCM_API SCM scm_set_debug_cell_accesses_x (SCM flag);
 
 SCM_API SCM scm_object_address (SCM obj);
 SCM_API SCM scm_gc_enable (void);
+SCM_API SCM scm_gc_smob_mark_report (void);
 SCM_API SCM scm_gc_disable (void);
 SCM_API SCM scm_gc_dump (void);
 SCM_API SCM scm_gc_stats (void);
diff --git a/libguile/smob.c b/libguile/smob.c
index c2e8f24..cc8b59a 100644
--- a/libguile/smob.c
+++ b/libguile/smob.c
@@ -52,6 +52,7 @@
 
 long scm_numsmob;
 scm_smob_descriptor scm_smobs[MAX_SMOB_COUNT];
+long scm_mark_from_null = 0, scm_mark_from_current = 0;
 
 void
 scm_assert_smob_type (scm_t_bits tag, SCM val)
@@ -294,6 +295,11 @@ smob_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
   register SCM cell;
   register scm_t_bits tc, smobnum;
 
+  if (SCM_I_CURRENT_THREAD == NULL)
+    scm_mark_from_null ++;
+  else
+    scm_mark_from_current ++;
+
   cell = PTR2SCM (addr);
 
   if (SCM_TYP7 (cell) != scm_tc7_smob)
@@ -318,7 +324,7 @@ smob_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
 				     mark_stack_ptr,
 				     mark_stack_limit, NULL);
 
-  if (scm_smobs[smobnum].mark)
+  if (scm_smobs[smobnum].mark && SCM_I_CURRENT_THREAD != NULL)
     {
       SCM obj;
 
-- 
1.7.11.7


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

* bug#13611: SEGV during SMOB GC
  2013-02-05 16:29   ` Mike Gran
@ 2013-02-05 16:41     ` Ludovic Courtès
  2013-02-05 17:04       ` Mike Gran
  0 siblings, 1 reply; 9+ messages in thread
From: Ludovic Courtès @ 2013-02-05 16:41 UTC (permalink / raw)
  To: Mike Gran; +Cc: 13611@debbugs.gnu.org

Hi,

Mike Gran <spk121@yahoo.com> skribis:

>> From: Ludovic Courtès <ludo@gnu.org>
>
>> Is there any chance that you’re using a GC 7.3 pre-release?
>
> Using gc-7.2b-2.fc17.i686

OK.

>> There was a similar report on IRC, and the fix appears to be:
>
> It does fix my SEGV

Good.

[...]

>  Count of GC SMOB marks from null thread: 176
>  Count of GC SMOB marks from current thread: 825
>
> Is that expected that GC is sometimes called from a 
> thread where scm_i_current_thread is null and sometimes
> called from a thread where scm_i_current_thread is
> not null?

Can you check whether your GC was built with --enable-parallel-mark?

I’m confident that the SMOB mark procedure is never called with null
scm_i_current_thread with 7.2 compiled with the default options (the
GnuTLS bindings rely on this, and I had not seen any such report until
someone tried with GC 7.3pre, which uses the parallel marker by
default.)

Thanks!

Ludo’.





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

* bug#13611: SEGV during SMOB GC
  2013-02-05 16:41     ` Ludovic Courtès
@ 2013-02-05 17:04       ` Mike Gran
  2013-02-05 21:13         ` Ludovic Courtès
  0 siblings, 1 reply; 9+ messages in thread
From: Mike Gran @ 2013-02-05 17:04 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 13611@debbugs.gnu.org

>>  Is that expected that GC is sometimes called from a 

>>  thread where scm_i_current_thread is null and sometimes
>>  called from a thread where scm_i_current_thread is
>>  not null?
> 
> Can you check whether your GC was built with --enable-parallel-mark?
> 
> I’m confident that the SMOB mark procedure is never called with null
> scm_i_current_thread with 7.2 compiled with the default options (the
> GnuTLS bindings rely on this, and I had not seen any such report until
> someone tried with GC 7.3pre, which uses the parallel marker by
> default.)

It looks like fedora gc rpms do use --enable-parallel-mark
for x86 architectures.

You can see that here:
  http://pkgs.fedoraproject.org/cgit/gc.git/tree/gc.spec?h=f17

But it looks like it has been that way for a long time.
Since 2005 at least.

-Mike





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

* bug#13611: SEGV during SMOB GC
  2013-02-05 17:04       ` Mike Gran
@ 2013-02-05 21:13         ` Ludovic Courtès
  2013-02-06  4:56           ` Mike Gran
  0 siblings, 1 reply; 9+ messages in thread
From: Ludovic Courtès @ 2013-02-05 21:13 UTC (permalink / raw)
  To: Mike Gran; +Cc: 13611@debbugs.gnu.org

Mike Gran <spk121@yahoo.com> skribis:

>>>  Is that expected that GC is sometimes called from a 
>
>>>  thread where scm_i_current_thread is null and sometimes
>>>  called from a thread where scm_i_current_thread is
>>>  not null?
>> 
>> Can you check whether your GC was built with --enable-parallel-mark?
>> 
>> I’m confident that the SMOB mark procedure is never called with null
>> scm_i_current_thread with 7.2 compiled with the default options (the
>> GnuTLS bindings rely on this, and I had not seen any such report until
>> someone tried with GC 7.3pre, which uses the parallel marker by
>> default.)
>
> It looks like fedora gc rpms do use --enable-parallel-mark
> for x86 architectures.

Then that’s the problem.

> But it looks like it has been that way for a long time.
> Since 2005 at least.

And you did not have the problem before?  That part of Guile hasn’t
changed in a long time, I think.

Ludo’.





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

* bug#13611: SEGV during SMOB GC
  2013-02-05 21:13         ` Ludovic Courtès
@ 2013-02-06  4:56           ` Mike Gran
  2013-03-01 17:02             ` Ludovic Courtès
  0 siblings, 1 reply; 9+ messages in thread
From: Mike Gran @ 2013-02-06  4:56 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 13611@debbugs.gnu.org

> From: Ludovic Courtès <ludo@gnu.org>

>>>  I’m confident that the SMOB mark procedure is never called with null
>>>  scm_i_current_thread with 7.2 compiled with the default options (the
>>>  GnuTLS bindings rely on this, and I had not seen any such report until
>>>  someone tried with GC 7.3pre, which uses the parallel marker by
>>>  default.)
>> 
>>  It looks like fedora gc rpms do use --enable-parallel-mark
>>  for x86 architectures.
> 
> Then that’s the problem.
> 
>>  But it looks like it has been that way for a long time.
>>  Since 2005 at least.
> 
> And you did not have the problem before?  That part of Guile hasn’t
> changed in a long time, I think.

I have a different box than before: more cores.

Well, I guess that, for my libraries, I can make a preprocessor conditional
on SCM_MAJOR_VERSION == 2 to eliminate all smob marking for guile-2.x.

Could parallel marking have other, non-SMOB-related, side effects?
I can disable it by setting the envirnomnent variable GC_MARKERS to 1.

Thanks,

Mike






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

* bug#13611: SEGV during SMOB GC
  2013-02-06  4:56           ` Mike Gran
@ 2013-03-01 17:02             ` Ludovic Courtès
  2013-03-13 12:42               ` Andy Wingo
  0 siblings, 1 reply; 9+ messages in thread
From: Ludovic Courtès @ 2013-03-01 17:02 UTC (permalink / raw)
  To: Mike Gran; +Cc: 13611

Hi Mike,

AFAICS, commit 01b69e7 fixes the problem for me.  I tested with your
test-smob-mark.c program, both with a 7.2ish and 7.3ish libgc.

Can you confirm that it works for you, and commit your test case with
the changes as discussed on the list?

Thanks!

Ludo’.





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

* bug#13611: SEGV during SMOB GC
  2013-03-01 17:02             ` Ludovic Courtès
@ 2013-03-13 12:42               ` Andy Wingo
  0 siblings, 0 replies; 9+ messages in thread
From: Andy Wingo @ 2013-03-13 12:42 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 13611-done, Mike Gran

On Fri 01 Mar 2013 18:02, ludo@gnu.org (Ludovic Courtès) writes:

> AFAICS, commit 01b69e7 fixes the problem for me.  I tested with your
> test-smob-mark.c program, both with a 7.2ish and 7.3ish libgc.
>
> Can you confirm that it works for you, and commit your test case with
> the changes as discussed on the list?

Changes committed, closing bug.  Thanks, all!

Andy
-- 
http://wingolog.org/





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

end of thread, other threads:[~2013-03-13 12:42 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-02 20:51 bug#13611: SEGV during SMOB GC Mike Gran
2013-02-05 10:07 ` Ludovic Courtès
2013-02-05 16:29   ` Mike Gran
2013-02-05 16:41     ` Ludovic Courtès
2013-02-05 17:04       ` Mike Gran
2013-02-05 21:13         ` Ludovic Courtès
2013-02-06  4:56           ` Mike Gran
2013-03-01 17:02             ` Ludovic Courtès
2013-03-13 12:42               ` 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).