Ferada/cl-cffi-gtk

Tests fail: Unhandled memory fault at #x0.

Ambrevar opened this issue · 17 comments

I'm trying to package cl-cffi-gtk for Guix but tests are failing:

; compiling (TEST G-SIGNAL-HAS-HANDLER-PENDING ...)

; /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals-tmpX2JYJDQE.fasl written
; compilation finished in 0:00:00.002
CORRUPTION WARNING in SBCL pid 17(tid 0x7ffff7ff41c0):
Memory fault at (nil) (pc=0x7ffff1339339, sp=0x7ffff6e05b90)
The integrity of this image is possibly compromised.
Continuing with fingers crossed.
Unhandled SB-SYS:MEMORY-FAULT-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
                                                 {10005585B3}>:
  Unhandled memory fault at #x0.

Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10005585B3}>
0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<SB-SYS:MEMORY-FAULT-ERROR {1002DA6433}> #<unused argument> :QUIT T)
1: (SB-DEBUG::RUN-HOOK SB-EXT:*INVOKE-DEBUGGER-HOOK* #<SB-SYS:MEMORY-FAULT-ERROR {1002DA6433}>)
2: (INVOKE-DEBUGGER #<SB-SYS:MEMORY-FAULT-ERROR {1002DA6433}>)
3: (ERROR SB-SYS:MEMORY-FAULT-ERROR :ADDRESS 0)
4: (SB-SYS:MEMORY-FAULT-ERROR #<unused argument> #.(SB-SYS:INT-SAP #X00000000))
5: ("foreign function: call_into_lisp")
6: ("foreign function: funcall2")
7: ("foreign function: handle_memory_fault_emulation_trap")
8: ("foreign function: handle_trap")
9: ("foreign function: #x41ABC3")
10: (GOBJECT::CALL-GOBJECT-CONSTRUCTOR "GtkButton" NIL NIL NIL)
11: (GOBJECT::CREATE-GOBJECT-FROM-CLASS #<GOBJECT-CLASS GTK:GTK-BUTTON> NIL)
12: ((:METHOD MAKE-INSTANCE (GOBJECT-CLASS)) #<GOBJECT-CLASS GTK:GTK-BUTTON>) [fast-method]
13: (SB-FASL::LOAD-FASL-GROUP #S(SB-FASL::FASL-INPUT :STREAM #<SB-SYS:FD-STREAM for "file /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" {1002D94E93}> :TABLE #(65 SET *PACKAGE* "GTK-TESTSUITE" #<PACKAGE "IT.BESE.FIVEAM"> MAKE-SUITE #<PACKAGE "GTK-TESTSUITE"> GOBJECT-SIGNALS :IN GOBJECT-SUITE GET-TEST SETF ...) :STACK #(0 MAKE-INSTANCE GTK-BUTTON NIL (SB-INT:SFUNCTION NIL NULL) NIL NULL :IN 21424 CERROR 19128 GET-TEST ...) :NAME-BUFFER #("\0" "GTK-BUTTONNCEG-FUN-TOPLEVEL\0\0\0\0") :DEPRECATED-STUFF NIL :SKIP-UNTIL NIL) NIL)
14: (SB-FASL::LOAD-AS-FASL #<SB-SYS:FD-STREAM for "file /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" {1002D94E93}> NIL NIL)
15: ((FLET SB-FASL::THUNK :IN LOAD))
16: (SB-FASL::CALL-WITH-LOAD-BINDINGS #<CLOSURE (FLET SB-FASL::THUNK :IN LOAD) {7FFFF6E067CB}> #<SB-SYS:FD-STREAM for "file /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" {1002D94E93}>)
17: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-SYS:FD-STREAM for "file /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" {1002D94E93}> T)
18: (LOAD #P"/gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :DEFAULT)
19: (UIOP/UTILITY:CALL-WITH-MUFFLED-CONDITIONS #<CLOSURE (LAMBDA NIL :IN UIOP/LISP-BUILD:LOAD*) {1002D938EB}> ("Overwriting already existing readtable ~S." #(#:FINALIZERS-OFF-WARNING :ASDF-FINALIZERS)))
20: ((SB-PCL::EMF ASDF/ACTION:PERFORM) #<unused argument> #<unused argument> #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "cl-cffi-gtk-test" "rtest-gobject-signals">)
21: ((LAMBDA NIL :IN ASDF/ACTION:CALL-WHILE-VISITING-ACTION))
22: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (ASDF/LISP-ACTION:LOAD-OP ASDF/LISP-ACTION:CL-SOURCE-FILE)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "cl-cffi-gtk-test" "rtest-gobject-signals">) [fast-method]
23: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS :AROUND (T T)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "cl-cffi-gtk-test" "rtest-gobject-signals">) [fast-method]
24: ((:METHOD ASDF/PLAN:PERFORM-PLAN (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN {1002325373}>) [fast-method]
25: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
26: ((:METHOD ASDF/PLAN:PERFORM-PLAN :AROUND (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN {1002325373}>) [fast-method]
27: ((:METHOD ASDF/OPERATE:OPERATE (ASDF/OPERATION:OPERATION ASDF/COMPONENT:COMPONENT)) #<ASDF/LISP-ACTION:TEST-OP > #<ASDF/SYSTEM:SYSTEM "cl-cffi-gtk"> :PLAN-CLASS NIL :PLAN-OPTIONS NIL) [fast-method]
28: ((SB-PCL::EMF ASDF/OPERATE:OPERATE) #<unused argument> #<unused argument> #<ASDF/LISP-ACTION:TEST-OP > #<ASDF/SYSTEM:SYSTEM "cl-cffi-gtk">)
29: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
30: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) #<ASDF/LISP-ACTION:TEST-OP > #<ASDF/SYSTEM:SYSTEM "cl-cffi-gtk">) [fast-method]
31: ((SB-PCL::EMF ASDF/OPERATE:OPERATE) #<unused argument> #<unused argument> ASDF/LISP-ACTION:TEST-OP "cl-cffi-gtk")
32: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
33: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) ASDF/LISP-ACTION:TEST-OP "cl-cffi-gtk") [fast-method]
34: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<CLOSURE (LAMBDA NIL :IN ASDF/OPERATE:OPERATE) {10021BAA2B}> :OVERRIDE T :KEY NIL :OVERRIDE-CACHE T :OVERRIDE-FORCING NIL)
35: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
36: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<CLOSURE (LAMBDA NIL :IN ASDF/OPERATE:OPERATE) {10041D7B0B}> :OVERRIDE NIL :KEY NIL :OVERRIDE-CACHE NIL :OVERRIDE-FORCING NIL)
37: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) ASDF/LISP-ACTION:TEST-OP "cl-cffi-gtk") [fast-method]
38: (ASDF/OPERATE:TEST-SYSTEM "cl-cffi-gtk")
39: (SB-INT:SIMPLE-EVAL-IN-LEXENV (ASDF/OPERATE:TEST-SYSTEM "cl-cffi-gtk") #<NULL-LEXENV>)
40: (EVAL (ASDF/OPERATE:TEST-SYSTEM "cl-cffi-gtk"))
41: (SB-IMPL::PROCESS-EVAL/LOAD-OPTIONS ((:EVAL . "(require :asdf)") (:EVAL . #<(SIMPLE-ARRAY CHARACTER (344)) (let ((*package* (find-package :asdf))) (load "/gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/share/common-lisp/sbcl-source/cl-cffi-gtk/gtk/cl-cffi-gtk.asd") (load "/gnu... {1001C2D0BF}>) (:EVAL . "(asdf:test-system \"cl-cffi-gtk\")") (:QUIT)))
42: (SB-IMPL::TOPLEVEL-INIT)
43: ((FLET SB-UNIX::BODY :IN SB-EXT:SAVE-LISP-AND-DIE))
44: ((FLET "WITHOUT-INTERRUPTS-BODY-27" :IN SB-EXT:SAVE-LISP-AND-DIE))
45: ((LABELS SB-IMPL::RESTART-LISP :IN SB-EXT:SAVE-LISP-AND-DIE))
; compiling (TEST G-SIGNAL-HAS-HANDLER-PENDING ...)

; /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals-tmpX2JYJDQE.fasl written
; compilation finished in 0:00:00.002
CORRUPTION WARNING in SBCL pid 17(tid 0x7ffff7ff41c0):
Memory fault at (nil) (pc=0x7ffff1339339, sp=0x7ffff6e05b90)
The integrity of this image is possibly compromised.
Continuing with fingers crossed.
Unhandled SB-SYS:MEMORY-FAULT-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
                                                 {10005585B3}>:
  Unhandled memory fault at #x0.

Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10005585B3}>
0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<SB-SYS:MEMORY-FAULT-ERROR {1002DA6433}> #<unused argument> :QUIT T)
1: (SB-DEBUG::RUN-HOOK SB-EXT:*INVOKE-DEBUGGER-HOOK* #<SB-SYS:MEMORY-FAULT-ERROR {1002DA6433}>)
2: (INVOKE-DEBUGGER #<SB-SYS:MEMORY-FAULT-ERROR {1002DA6433}>)
3: (ERROR SB-SYS:MEMORY-FAULT-ERROR :ADDRESS 0)
4: (SB-SYS:MEMORY-FAULT-ERROR #<unused argument> #.(SB-SYS:INT-SAP #X00000000))
5: ("foreign function: call_into_lisp")
6: ("foreign function: funcall2")
7: ("foreign function: handle_memory_fault_emulation_trap")
8: ("foreign function: handle_trap")
9: ("foreign function: #x41ABC3")
10: (GOBJECT::CALL-GOBJECT-CONSTRUCTOR "GtkButton" NIL NIL NIL)
11: (GOBJECT::CREATE-GOBJECT-FROM-CLASS #<GOBJECT-CLASS GTK:GTK-BUTTON> NIL)
12: ((:METHOD MAKE-INSTANCE (GOBJECT-CLASS)) #<GOBJECT-CLASS GTK:GTK-BUTTON>) [fast-method]
13: (SB-FASL::LOAD-FASL-GROUP #S(SB-FASL::FASL-INPUT :STREAM #<SB-SYS:FD-STREAM for "file /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" {1002D94E93}> :TABLE #(65 SET *PACKAGE* "GTK-TESTSUITE" #<PACKAGE "IT.BESE.FIVEAM"> MAKE-SUITE #<PACKAGE "GTK-TESTSUITE"> GOBJECT-SIGNALS :IN GOBJECT-SUITE GET-TEST SETF ...) :STACK #(0 MAKE-INSTANCE GTK-BUTTON NIL (SB-INT:SFUNCTION NIL NULL) NIL NULL :IN 21424 CERROR 19128 GET-TEST ...) :NAME-BUFFER #("\0" "GTK-BUTTONNCEG-FUN-TOPLEVEL\0\0\0\0") :DEPRECATED-STUFF NIL :SKIP-UNTIL NIL) NIL)
14: (SB-FASL::LOAD-AS-FASL #<SB-SYS:FD-STREAM for "file /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" {1002D94E93}> NIL NIL)
15: ((FLET SB-FASL::THUNK :IN LOAD))
16: (SB-FASL::CALL-WITH-LOAD-BINDINGS #<CLOSURE (FLET SB-FASL::THUNK :IN LOAD) {7FFFF6E067CB}> #<SB-SYS:FD-STREAM for "file /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" {1002D94E93}>)
17: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-SYS:FD-STREAM for "file /gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" {1002D94E93}> T)
18: (LOAD #P"/gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/lib/sbcl/test/rtest-gobject-signals.fasl" :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :DEFAULT)
19: (UIOP/UTILITY:CALL-WITH-MUFFLED-CONDITIONS #<CLOSURE (LAMBDA NIL :IN UIOP/LISP-BUILD:LOAD*) {1002D938EB}> ("Overwriting already existing readtable ~S." #(#:FINALIZERS-OFF-WARNING :ASDF-FINALIZERS)))
20: ((SB-PCL::EMF ASDF/ACTION:PERFORM) #<unused argument> #<unused argument> #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "cl-cffi-gtk-test" "rtest-gobject-signals">)
21: ((LAMBDA NIL :IN ASDF/ACTION:CALL-WHILE-VISITING-ACTION))
22: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (ASDF/LISP-ACTION:LOAD-OP ASDF/LISP-ACTION:CL-SOURCE-FILE)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "cl-cffi-gtk-test" "rtest-gobject-signals">) [fast-method]
23: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS :AROUND (T T)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "cl-cffi-gtk-test" "rtest-gobject-signals">) [fast-method]
24: ((:METHOD ASDF/PLAN:PERFORM-PLAN (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN {1002325373}>) [fast-method]
25: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
26: ((:METHOD ASDF/PLAN:PERFORM-PLAN :AROUND (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN {1002325373}>) [fast-method]
27: ((:METHOD ASDF/OPERATE:OPERATE (ASDF/OPERATION:OPERATION ASDF/COMPONENT:COMPONENT)) #<ASDF/LISP-ACTION:TEST-OP > #<ASDF/SYSTEM:SYSTEM "cl-cffi-gtk"> :PLAN-CLASS NIL :PLAN-OPTIONS NIL) [fast-method]
28: ((SB-PCL::EMF ASDF/OPERATE:OPERATE) #<unused argument> #<unused argument> #<ASDF/LISP-ACTION:TEST-OP > #<ASDF/SYSTEM:SYSTEM "cl-cffi-gtk">)
29: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
30: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) #<ASDF/LISP-ACTION:TEST-OP > #<ASDF/SYSTEM:SYSTEM "cl-cffi-gtk">) [fast-method]
31: ((SB-PCL::EMF ASDF/OPERATE:OPERATE) #<unused argument> #<unused argument> ASDF/LISP-ACTION:TEST-OP "cl-cffi-gtk")
32: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
33: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) ASDF/LISP-ACTION:TEST-OP "cl-cffi-gtk") [fast-method]
34: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<CLOSURE (LAMBDA NIL :IN ASDF/OPERATE:OPERATE) {10021BAA2B}> :OVERRIDE T :KEY NIL :OVERRIDE-CACHE T :OVERRIDE-FORCING NIL)
35: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
36: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<CLOSURE (LAMBDA NIL :IN ASDF/OPERATE:OPERATE) {10041D7B0B}> :OVERRIDE NIL :KEY NIL :OVERRIDE-CACHE NIL :OVERRIDE-FORCING NIL)
37: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) ASDF/LISP-ACTION:TEST-OP "cl-cffi-gtk") [fast-method]
38: (ASDF/OPERATE:TEST-SYSTEM "cl-cffi-gtk")
39: (SB-INT:SIMPLE-EVAL-IN-LEXENV (ASDF/OPERATE:TEST-SYSTEM "cl-cffi-gtk") #<NULL-LEXENV>)
40: (EVAL (ASDF/OPERATE:TEST-SYSTEM "cl-cffi-gtk"))
41: (SB-IMPL::PROCESS-EVAL/LOAD-OPTIONS ((:EVAL . "(require :asdf)") (:EVAL . #<(SIMPLE-ARRAY CHARACTER (344)) (let ((*package* (find-package :asdf))) (load "/gnu/store/3147aza1waksp76pllkifskyym4wmqvg-sbcl-cl-cffi-gtk-0.11.2-1.29443c5/share/common-lisp/sbcl-source/cl-cffi-gtk/gtk/cl-cffi-gtk.asd") (load "/gnu... {1001C2D0BF}>) (:EVAL . "(asdf:test-system \"cl-cffi-gtk\")") (:QUIT)))
42: (SB-IMPL::TOPLEVEL-INIT)
43: ((FLET SB-UNIX::BODY :IN SB-EXT:SAVE-LISP-AND-DIE))
44: ((FLET "WITHOUT-INTERRUPTS-BODY-27" :IN SB-EXT:SAVE-LISP-AND-DIE))
45: ((LABELS SB-IMPL::RESTART-LISP :IN SB-EXT:SAVE-LISP-AND-DIE))

Can anyone reproduce?

Which SBCL version (or commit) is that? And which GTK/G... versions? I'll try reproducing it, though actually I'll only be able to check with a different SBCL version, GTK is too much of a hassle.

SBCL 1.4.4.

GTK 3.22.30.

Works for me unfortunately. SBCL master, a few commits after 1.4.12, GTK a few commits after 3.22.21. I might be able to check this on another machine, though it might also take some time.


On a fresh process, with cl-cffi-gtk loaded, does the following not crash and return a pointer?

(cffi:with-foreign-object (parameters '(:struct gobject::g-parameter) 0) (gobject::g-object-newv "GtkButton" 0 parameters))

That's very likely the call that failed in the output above and it really shouldn't, since that goes straight to the FFI level.

On Guix, the filesystem is slightly different and the libraries are found in ~/.guix-profile/lib, so to load cffi-related libraries I make sure to add this folder to cffi:*foreign-library-directories*.

The result is as follows:

> sbcl
This is SBCL 1.4.4, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (ql:quickload :cffi)
To load "cffi":
  Load 1 ASDF system:
    cffi
; Loading "cffi"
.
(:CFFI)
* (push (format nil "~a/.guix-profile/lib/" (uiop:getenv "HOME")) cffi:*foreign-library-directories*)

("/home/ambrevar/.guix-profile/lib/")
* (ql:quickload "cl-cffi-gtk")
To load "cl-cffi-gtk":
  Load 1 ASDF system:
    cl-cffi-gtk
; Loading "cl-cffi-gtk"
..............
("cl-cffi-gtk")
* (cffi:with-foreign-object (parameters '(:struct gobject::g-parameter) 0) (gobject::g-object-newv "GtkButton" 0 parameters))

#.(SB-SYS:INT-SAP #X00788180)
* 

And it works.

The above error is produced when the tests are run from the Guix' asdf-build-system which is used to package Common Lisp code.

That's Quicklisp's cl-cffi-gtk? AFAIK that's not been touched in ages. In which case you could try this (@Ferada's) repository and see if that changes things.

Oh, did not notice that. Shouldn't we let Quicklisp know?

I've tried this repo and got the same result.

Oh, did not notice that. Shouldn't we let Quicklisp know?

Be my guest, quicklisp/quicklisp-projects#1302.

I've tried this repo and got the same result.

Okay. Right now I have no real idea what else to try, except attach gdb and see where it fails ... looking at Guix to try would take me a while.

I've opened an issue on Guix' bug tracker, we might get some help from there.

This stacktrace looks a lot as if source-func-cb funcall:ed nil. If so, it might be another aspect of stable-pointers not being thread-safe.
See crategus#73
There I talk about side-threads, but I believe that even the main thread of gtk can sometimes call signal handlers in parallel threads.

Using side-threads, the following triggers an error pretty reliably.

(defun touch-gtk-label (gtk-label)
  (sleep (random 0.001))
  (within-gtk-thread
    (sleep (random 0.001))
    (gtk-label-set-text gtk-label "LISP")))

(defclass clicker (widget)
  ((gtk-label :initarg :gtk-label :reader gtk-label)))
(defmethod clicked ((c clicker))
  (dotimes (i 100)
    (sb-thread:make-thread (lambda () (touch-gtk-label (gtk-label c))))))

(defun start-test ()
  (within-main-loop
    (with-build-interface ("lisp/issue-test/issue-test.glade" 'issue-test builder t)
      (let ((top (gtk-builder-get-object builder "top"))
            (label-a (gtk-builder-get-object builder "label-a")))
        (gtk-widget-show-all top)
        (list (cons "clicker" (make-instance 'clicker :gtk-label label-a)))))))

This relies on my cl-gtk-frank, but it's just a callback for 'clicked' on a button which sets the text of a label.

The stack-trace I get is

  0: ("undefined function")
  1: ((LAMBDA (GDK::DATA) :IN "/home/bpatrikm/lisp/cl-cffi-gtk-master/gdk/gdk.threads.lisp") #.(SB-SYS:INT-SAP #X00000038))
  2: ((LAMBDA (SB-ALIEN::ARGS-POINTER SB-ALIEN::RESULT-POINTER FUNCTION) :IN "/home/bpatrikm/lisp/cl-cffi-gtk-master/glib/glib.main-loop.lisp") #<unavailable argument> #<unavailable argument> #<unavailable a..
  3: ("foreign function: funcall_alien_callback")
  4: ("foreign function: callback_wrapper_trampoline")
  5: ("foreign function: #x50100562")
  6: ((LAMBDA NIL :IN GTK:ENSURE-GTK-MAIN))
  7: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS))
...

This doesn't look exactly like your example, but I'm thinking that the difference in SBCL version (2.0.1 here) might account for that.

@bpatrikm I've edited your post to fix the formatting. Also please post a self-contained example whenever possible, I can't go chase dependencies for debugging.

Using side-threads

Is that a library?

This is what I've tried:

(in-package #:gtk)

(defun touch-gtk-label (gtk-label)
  (sleep (random 0.001))
  (within-gtk-thread
    (sleep (random 0.001))
    (gtk-label-set-text gtk-label "LISP")))

(defclass clicker ()
  ((gtk-label :initarg :gtk-label :reader gtk-label)))

(defmethod clicked ((c clicker))
  (dotimes (i 100)
    (bt:make-thread (lambda () (touch-gtk-label (gtk-label c))))))

(defvar *blah*)

(defun start-test ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window))
          (label (make-instance 'gtk-label)))
      (gtk-container-add window label)
      (gtk-widget-show-all window)
      (setf *blah* (make-instance 'clicker :gtk-label label)))))

And that works fairly well on Clozure CL, can't try right now on SBCL.

Note that (defclass clicker (widget) ... isn't valid as the superclass would have to be gtk-widget and even then that's missing a metaclass argument too. Also within-main-loop can't return a value since it's running concurrently, that's why I changed it to set a global instead.

@bpatrikm Could you increase your debug level for a better stacktrace? Like (declaim (optimize (debug 3) (safety 3))) or so.

This produces the same error for me.

(in-package #:gtk)

(defun touch-gtk-label (gtk-label)
  (sleep (random 0.001))
  (within-gtk-thread
    (sleep (random 0.001))
    (gtk-label-set-text gtk-label "LISP")))

(defclass clicker ()
  ((gtk-label :accessor gtk-label)))
(defmethod clicked ((c clicker))
  (dotimes (i 100)
    (bt:make-thread (lambda () (touch-gtk-label (gtk-label c))))))

(defvar *clicker* (make-instance 'clicker))

(defun start-test ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window))
          (box (make-instance 'gtk-box))
          (label (make-instance 'gtk-label :label "label"))
          (button (make-instance 'gtk-button :label "clicker")))
      (setf (gtk-label *clicker*) label)
      (gtk-container-add window box)
      (gtk-container-add box label)
      (gtk-container-add box button)
      (g-signal-connect button "clicked" (lambda (w) (clicked *clicker*)))
      (gtk-widget-show-all window))))

Note that the error is triggered when the button is clicked. There is a random element to it, but it triggers nine times out of ten for me.

Could you increase your debug level for a better stacktrace?

Changing the debug level makes no difference for me (in this or the former example).

Using side-threads

Is that a library?

By 'side-threads', I only mean the concept that new threads are created within the callback. Gtk has a concept of a 'main thread' - and I mean any other threads than that.

More important than an example, is to look at the lack of thread safety in glib.stable-pointer.lisp and gdk.threads.lisp. Although producing an error on demand is a bit fiddly, it's obvious one will happen sooner or later if stable-pointer is used concurrantly. Now, anytime you cause that to happen through using 'within-gtk-thread', you can also prevent it by setting up your own mutexes. But I have come to believe, that it may also happen that callbacks are invoked in side-threads, although the gtk documentations says it won't.

https://developer.gnome.org/gdk3/stable/gdk3-Threads.html

Signals on GTK+ and GDK types, as well as non-signal callbacks, are emitted in the main thread.

Okay, I'll see if I can reproduce it on SBCL.

glib.stable-pointer.lisp, gdk.threads.lisp

Perhaps, yes, if you put a mutex in/around allocate-stable-pointer, does the crash disappear then?

I also blame concurrency issues on some other trouble I've encountered, it's just impossible to debug.

I made those edits in glib.stable-pointer.lisp in my repo-copy. I'm wary of making a pull request of it, because I really don't know if it might cause other problems. But it does get rid of this crash.

Can confirm on SBCL and also your fix makes it disappear, I'll do some more testing with a bigger project, but feel free to make a PR for it.

(sp-mutex (bt:make-lock "sp-mutex")))

could you make that

(sp-mutex (bt:make-lock "stable-pointers lock")))

so it matches other calls to make-lock.