Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code shown below. Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 + LLVM. No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit 4.8.2. Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed multiple times to another c-lambda procedure (*->My). It's a simplified model of the code produced by a FFI SDL2 Library I'm using. The doc says that the foreign object (xoxo in the example) should not be released while the scheme code is still referencing it. I am seeing the refcount going wildly in the negative, one for each call to *->My The only way -- clumsy -- I have found to avoid this is to increment the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped * thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt * thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) * frame #0: 0x000000010000770c fromlin`___release_rc + 28 frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950 (lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));")) (define *->My (c-lambda (My*/nonnull) My "___result_voidstar = (My*)___arg1;")) (define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result = ___arg1->r;")) (define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void "___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Afficher les réponses par date
I'm interested in understanding what caused that sigsegv too.
2015-12-14 17:55 GMT+08:00 Paolo Carlesi pcarlesi@gmail.com:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code shown below. Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 + LLVM. No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit 4.8.2. Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed multiple times to another c-lambda procedure (*->My). It's a simplified model of the code produced by a FFI SDL2 Library I'm using. The doc says that the foreign object (xoxo in the example) should not be released while the scheme code is still referencing it. I am seeing the refcount going wildly in the negative, one for each call to *->My The only way -- clumsy -- I have found to avoid this is to increment the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc +
28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc +
28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28 frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950
(lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar =
___EXT(___alloc_rc)( sizeof( struct My ));")) (define *->My (c-lambda (My*/nonnull) My "___result_voidstar = (My*)___arg1;")) (define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result = ___arg1->r;")) (define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void "___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
There appears to be a bug in the FFI when using a c-lambda with inline code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code shown below. Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 + LLVM. No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit 4.8.2. Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed multiple times to another c-lambda procedure (*->My). It's a simplified model of the code produced by a FFI SDL2 Library I'm using. The doc says that the foreign object (xoxo in the example) should not be released while the scheme code is still referencing it. I am seeing the refcount going wildly in the negative, one for each call to *->My The only way -- clumsy -- I have found to avoid this is to increment the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x000000010000770c fromlin`___release_rc + 28
fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28 frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950
(lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));")) (define *->My (c-lambda (My*/nonnull) My "___result_voidstar = (My*)___arg1;")) (define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result = ___arg1->r;")) (define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void "___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Marc,
Can you please give us a more exact definition of this bug - does it only apply when returning a pointered c-define-type type from inlined C code to Scheme, or does it affect inlined code returning a ___SCMOBJ too?
Also if you could provide a patch (as this is the only severe Gambit bug that has been for like 2-3 years) would be great.
Thanks!
2015-12-15 1:02 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca:
There appears to be a bug in the FFI when using a c-lambda with inline code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code
shown below.
Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 +
LLVM.
No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit
4.8.2.
Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed
multiple times to another c-lambda procedure (*->My).
It's a simplified model of the code produced by a FFI SDL2 Library I'm
using.
The doc says that the foreign object (xoxo in the example) should not be
released while the scheme code is still referencing it.
I am seeing the refcount going wildly in the negative, one for each call
to *->My
The only way -- clumsy -- I have found to avoid this is to increment the
reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc +
28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc +
28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28 frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950
(lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*)
"___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar =
___EXT(___alloc_rc)( sizeof( struct My ));"))
(define *->My (c-lambda (My*/nonnull) My "___result_voidstar =
(My*)___arg1;"))
(define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result =
___arg1->r;"))
(define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void
"___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Marc,
Also, do you have any idea when the bug was introduced, do you think it was after or before 4.7.0?
Thanks
2015-12-15 1:22 GMT+08:00 Adam adam.mlmb@gmail.com:
Marc,
Can you please give us a more exact definition of this bug - does it only apply when returning a pointered c-define-type type from inlined C code to Scheme, or does it affect inlined code returning a ___SCMOBJ too?
Also if you could provide a patch (as this is the only severe Gambit bug that has been for like 2-3 years) would be great.
Thanks!
2015-12-15 1:02 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca:
There appears to be a bug in the FFI when using a c-lambda with inline code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code
shown below.
Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 +
LLVM.
No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit
4.8.2.
Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed
multiple times to another c-lambda procedure (*->My).
It's a simplified model of the code produced by a FFI SDL2 Library I'm
using.
The doc says that the foreign object (xoxo in the example) should not
be released while the scheme code is still referencing it.
I am seeing the refcount going wildly in the negative, one for each
call to *->My
The only way -- clumsy -- I have found to avoid this is to increment
the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc +
28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc +
28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28 frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950
(lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*)
"___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar =
___EXT(___alloc_rc)( sizeof( struct My ));"))
(define *->My (c-lambda (My*/nonnull) My "___result_voidstar =
(My*)___arg1;"))
(define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result =
___arg1->r;"))
(define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void
"___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Thank you for the workaround!
What is the best way to generate a foreign c-type object ?
This seems to me the best approach (sorry if it's obvious to everybody but me):
(define make-My (c-lambda () My "___result_voidstar = ___EXT(___alloc_rc)(sizeof(struct My));")) (define My->* (c-lambda (My) My*/nonnull "___result_voidstar = &___arg1;"))
has the advantage of not wasting time / space creating a new foreign object and a copy, like *->My below does. It also doesn't trigger the c-lambda bug, not that I have verified carefully yet. Members can easily be set up with a syntax like (My-x-set! (My->* xoxo) #xdeadbeef) . Is this approach correct?
Thanks Again
Paolo
Il giorno 14/dic/2015, alle ore 18:02, Marc Feeley feeley@iro.umontreal.ca ha scritto:
There appears to be a bug in the FFI when using a c-lambda with inline code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code shown below. Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 + LLVM. No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit 4.8.2. Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed multiple times to another c-lambda procedure (*->My). It's a simplified model of the code produced by a FFI SDL2 Library I'm using. The doc says that the foreign object (xoxo in the example) should not be released while the scheme code is still referencing it. I am seeing the refcount going wildly in the negative, one for each call to *->My The only way -- clumsy -- I have found to avoid this is to increment the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x000000010000770c fromlin`___release_rc + 28
fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28 frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950
(lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));")) (define *->My (c-lambda (My*/nonnull) My "___result_voidstar = (My*)___arg1;")) (define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result = ___arg1->r;")) (define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void "___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Paolo, wait, what is your definition of your My type here - "scheme-object"?
2015-12-15 3:46 GMT+08:00 Paolo Carlesi pcarlesi@gmail.com:
Thank you for the workaround!
What is the best way to generate a foreign c-type object ?
This seems to me the best approach (sorry if it's obvious to everybody but me):
(define make-My (c-lambda () My "___result_voidstar = ___EXT(___alloc_rc)(sizeof(struct My));")) (define My->* (c-lambda (My) My*/nonnull "___result_voidstar = &___arg1;"))
has the advantage of not wasting time / space creating a new foreign object and a copy, like *->My below does. It also doesn't trigger the c-lambda bug, not that I have verified carefully yet. Members can easily be set up with a syntax like (My-x-set! (My->* xoxo) #xdeadbeef) . Is this approach correct?
Thanks Again
Paolo
Il giorno 14/dic/2015, alle ore 18:02, Marc Feeley < feeley@iro.umontreal.ca> ha scritto:
There appears to be a bug in the FFI when using a c-lambda with inline
code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code
shown below.
Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 +
LLVM.
No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit
4.8.2.
Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed
multiple times to another c-lambda procedure (*->My).
It's a simplified model of the code produced by a FFI SDL2 Library I'm
using.
The doc says that the foreign object (xoxo in the example) should not
be released while the scheme code is still referencing it.
I am seeing the refcount going wildly in the negative, one for each
call to *->My
The only way -- clumsy -- I have found to avoid this is to increment
the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc +
28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc +
28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28 frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950
(lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*)
"___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar =
___EXT(___alloc_rc)( sizeof( struct My ));"))
(define *->My (c-lambda (My*/nonnull) My "___result_voidstar =
(My*)___arg1;"))
(define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result =
___arg1->r;"))
(define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void
"___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
"My" is the struct I've been showing in my other email, defined inside a C-declare and wrapped by c-define-type. From gambit's point of viewI it is a scheme-object like everything else, I suppose.
Here is the code. For whatever reason "new-My" doesn't trigger the bug in my simple use case, even if it returns an object. I was wrong about a detail: that bug is also present in linux. Doesn't crash, but corrupts the contents of the structure (!).
;; START
(c-declare #<<c-declare-end typedef struct My { int r; } My;
static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); }
// workaround to c-lambda bug (gambit mailing list 2015-12-14 My indirect_star_to_My(My *ptr) { return *ptr; } c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));")) (define *->My (c-lambda (My*/nonnull) My "indirect_star_to_My")) (define My-r (c-lambda (My*/nonnull) int "___result = ___arg1->r;")) (define My-r-set! (c-lambda (My*/nonnull int) void "___arg1->r = ___arg2;")) (define My->* (c-lambda (My) My*/nonnull "___result_voidstar = &___arg1;"))
;; this one returns My, as a foreign object (struct), not as a foreign object (pointer) ;; doesn't segfault, at least in my use case. why? (define new-My (c-lambda () My "___result_voidstar = ___EXT(___alloc_rc)(sizeof(struct My));"))
(define (evil) (let* ((xoxo (new-My)) (xoxop (My->* xoxo))) (My-r-set! xoxop #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 1000000)) (begin (display c) (display "-") (display (My-r xoxop)) (newline))) (loop (+ 1 c)))))) (evil)
;; END
Il giorno 15/dic/2015, alle ore 19:25, Adam adam.mlmb@gmail.com ha scritto:
Paolo, wait, what is your definition of your My type here - "scheme-object"?
2015-12-15 3:46 GMT+08:00 Paolo Carlesi pcarlesi@gmail.com: Thank you for the workaround!
What is the best way to generate a foreign c-type object ?
This seems to me the best approach (sorry if it's obvious to everybody but me):
(define make-My (c-lambda () My "___result_voidstar = ___EXT(___alloc_rc)(sizeof(struct My));")) (define My->* (c-lambda (My) My*/nonnull "___result_voidstar = &___arg1;"))
has the advantage of not wasting time / space creating a new foreign object and a copy, like *->My below does. It also doesn't trigger the c-lambda bug, not that I have verified carefully yet. Members can easily be set up with a syntax like (My-x-set! (My->* xoxo) #xdeadbeef) . Is this approach correct?
Thanks Again
Paolo
Il giorno 14/dic/2015, alle ore 18:02, Marc Feeley feeley@iro.umontreal.ca ha scritto:
There appears to be a bug in the FFI when using a c-lambda with inline code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code shown below. Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 + LLVM. No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit 4.8.2. Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed multiple times to another c-lambda procedure (*->My). It's a simplified model of the code produced by a FFI SDL2 Library I'm using. The doc says that the foreign object (xoxo in the example) should not be released while the scheme code is still referencing it. I am seeing the refcount going wildly in the negative, one for each call to *->My The only way -- clumsy -- I have found to avoid this is to increment the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x000000010000770c fromlin`___release_rc + 28
fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28 frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950
(lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));")) (define *->My (c-lambda (My*/nonnull) My "___result_voidstar = (My*)___arg1;")) (define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result = ___arg1->r;")) (define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void "___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
I have improved the FFI by introducing the ___return(val) macro which should be used from now on instead of ___result=val and ___result_voidstar=val. So your *->My function can be coded like this:
(define *->My (c-lambda (My*/nonnull) My "___return(*___arg1);"))
This will hide the implementation of the FFI and the use of ___result and ___result_voidstar, which was confusing.
Check the updated Gambit manual for details.
Marc
On Dec 14, 2015, at 2:46 PM, Paolo Carlesi pcarlesi@gmail.com wrote:
Thank you for the workaround!
What is the best way to generate a foreign c-type object ?
This seems to me the best approach (sorry if it's obvious to everybody but me):
(define make-My (c-lambda () My "___result_voidstar = ___EXT(___alloc_rc)(sizeof(struct My));")) (define My->* (c-lambda (My) My*/nonnull "___result_voidstar = &___arg1;"))
has the advantage of not wasting time / space creating a new foreign object and a copy, like *->My below does. It also doesn't trigger the c-lambda bug, not that I have verified carefully yet. Members can easily be set up with a syntax like (My-x-set! (My->* xoxo) #xdeadbeef) . Is this approach correct?
Thanks Again
Paolo
Il giorno 14/dic/2015, alle ore 18:02, Marc Feeley feeley@iro.umontreal.ca ha scritto:
There appears to be a bug in the FFI when using a c-lambda with inline code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code shown below. Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 + LLVM. No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit 4.8.2. Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed multiple times to another c-lambda procedure (*->My). It's a simplified model of the code produced by a FFI SDL2 Library I'm using. The doc says that the foreign object (xoxo in the example) should not be released while the scheme code is still referencing it. I am seeing the refcount going wildly in the negative, one for each call to *->My The only way -- clumsy -- I have found to avoid this is to increment the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28
frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950 (lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));")) (define *->My (c-lambda (My*/nonnull) My "___result_voidstar = (My*)___arg1;")) (define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result = ___arg1->r;")) (define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void "___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Neat!
What was the problem with ___result ?
And, in what commit did you introduce ___return ?
2015-12-17 7:00 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca:
I have improved the FFI by introducing the ___return(val) macro which should be used from now on instead of ___result=val and ___result_voidstar=val. So your *->My function can be coded like this:
(define *->My (c-lambda (My*/nonnull) My "___return(*___arg1);"))
This will hide the implementation of the FFI and the use of ___result and ___result_voidstar, which was confusing.
Check the updated Gambit manual for details.
Marc
On Dec 14, 2015, at 2:46 PM, Paolo Carlesi pcarlesi@gmail.com wrote:
Thank you for the workaround!
What is the best way to generate a foreign c-type object ?
This seems to me the best approach (sorry if it's obvious to everybody
but me):
(define make-My (c-lambda () My "___result_voidstar =
___EXT(___alloc_rc)(sizeof(struct My));"))
(define My->* (c-lambda (My) My*/nonnull "___result_voidstar =
&___arg1;"))
has the advantage of not wasting time / space creating a new foreign
object and a copy, like *->My below does.
It also doesn't trigger the c-lambda bug, not that I have verified
carefully yet.
Members can easily be set up with a syntax like (My-x-set! (My->* xoxo)
#xdeadbeef) .
Is this approach correct?
Thanks Again
Paolo
Il giorno 14/dic/2015, alle ore 18:02, Marc Feeley <
feeley@iro.umontreal.ca> ha scritto:
There appears to be a bug in the FFI when using a c-lambda with inline
code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code
shown below.
Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 +
LLVM.
No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit
4.8.2.
Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed
multiple times to another c-lambda procedure (*->My).
It's a simplified model of the code produced by a FFI SDL2 Library I'm
using.
The doc says that the foreign object (xoxo in the example) should not
be released while the scheme code is still referencing it.
I am seeing the refcount going wildly in the negative, one for each
call to *->My
The only way -- clumsy -- I have found to avoid this is to increment
the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc
- 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS
(code=EXC_I386_GPFLT)
frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc
- 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS
(code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28
frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950 (lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*)
"___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar =
___EXT(___alloc_rc)( sizeof( struct My ));"))
(define *->My (c-lambda (My*/nonnull) My "___result_voidstar =
(My*)___arg1;"))
(define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result =
___arg1->r;"))
(define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void
"___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
It was added today in the latest commit.
The problem with using ___result and ___result_voidstar is that the programmer needs to know when to use one or the other, and this is related to the implementation of the FFI. Types such as int, double, char can use ___result directly, but “foreign data” such as structs, unions, opaque types, and pointers need to set ___result_voidstar.
In the case of values that are structs, unions and opaque types, a block of memory must be allocated, then initialized to the value, and ___result_voidstar is set to point to this block of memory. But how is the block of memory initialized with the value? Using an assignment works fine for C, but is not ideal when using C++… it is better to use the copy constructor in case the assignment operator is overloaded. This means that the allocation of the block of memory and its initialization needs to be combined in a single operation. The ___return macro hides all of these details so that the same code base will work in C and C++.
Marc
On Dec 16, 2015, at 6:27 PM, Adam adam.mlmb@gmail.com wrote:
Neat!
What was the problem with ___result ?
And, in what commit did you introduce ___return ?
2015-12-17 7:00 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca: I have improved the FFI by introducing the ___return(val) macro which should be used from now on instead of ___result=val and ___result_voidstar=val. So your *->My function can be coded like this:
(define *->My (c-lambda (My*/nonnull) My "___return(*___arg1);"))
This will hide the implementation of the FFI and the use of ___result and ___result_voidstar, which was confusing.
Check the updated Gambit manual for details.
Marc
On Dec 14, 2015, at 2:46 PM, Paolo Carlesi pcarlesi@gmail.com wrote:
Thank you for the workaround!
What is the best way to generate a foreign c-type object ?
This seems to me the best approach (sorry if it's obvious to everybody but me):
(define make-My (c-lambda () My "___result_voidstar = ___EXT(___alloc_rc)(sizeof(struct My));")) (define My->* (c-lambda (My) My*/nonnull "___result_voidstar = &___arg1;"))
has the advantage of not wasting time / space creating a new foreign object and a copy, like *->My below does. It also doesn't trigger the c-lambda bug, not that I have verified carefully yet. Members can easily be set up with a syntax like (My-x-set! (My->* xoxo) #xdeadbeef) . Is this approach correct?
Thanks Again
Paolo
Il giorno 14/dic/2015, alle ore 18:02, Marc Feeley feeley@iro.umontreal.ca ha scritto:
There appears to be a bug in the FFI when using a c-lambda with inline code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample code shown below. Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 + LLVM. No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit 4.8.2. Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed multiple times to another c-lambda procedure (*->My). It's a simplified model of the code produced by a FFI SDL2 Library I'm using. The doc says that the foreign object (xoxo in the example) should not be released while the scheme code is still referencing it. I am seeing the refcount going wildly in the negative, one for each call to *->My The only way -- clumsy -- I have found to avoid this is to increment the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28
frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950 (lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));")) (define *->My (c-lambda (My*/nonnull) My "___result_voidstar = (My*)___arg1;")) (define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result = ___arg1->r;")) (define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void "___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Ah ok.
But, was there a bug in the current code inlining behavior - in what Gambit version was that bug introduced?
2015-12-17 8:11 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca:
It was added today in the latest commit.
The problem with using ___result and ___result_voidstar is that the programmer needs to know when to use one or the other, and this is related to the implementation of the FFI. Types such as int, double, char can use ___result directly, but “foreign data” such as structs, unions, opaque types, and pointers need to set ___result_voidstar.
In the case of values that are structs, unions and opaque types, a block of memory must be allocated, then initialized to the value, and ___result_voidstar is set to point to this block of memory. But how is the block of memory initialized with the value? Using an assignment works fine for C, but is not ideal when using C++… it is better to use the copy constructor in case the assignment operator is overloaded. This means that the allocation of the block of memory and its initialization needs to be combined in a single operation. The ___return macro hides all of these details so that the same code base will work in C and C++.
Marc
On Dec 16, 2015, at 6:27 PM, Adam adam.mlmb@gmail.com wrote:
Neat!
What was the problem with ___result ?
And, in what commit did you introduce ___return ?
2015-12-17 7:00 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca: I have improved the FFI by introducing the ___return(val) macro which
should be used from now on instead of ___result=val and ___result_voidstar=val. So your *->My function can be coded like this:
(define *->My (c-lambda (My*/nonnull) My "___return(*___arg1);"))
This will hide the implementation of the FFI and the use of ___result
and ___result_voidstar, which was confusing.
Check the updated Gambit manual for details.
Marc
On Dec 14, 2015, at 2:46 PM, Paolo Carlesi pcarlesi@gmail.com wrote:
Thank you for the workaround!
What is the best way to generate a foreign c-type object ?
This seems to me the best approach (sorry if it's obvious to everybody
but me):
(define make-My (c-lambda () My "___result_voidstar =
___EXT(___alloc_rc)(sizeof(struct My));"))
(define My->* (c-lambda (My) My*/nonnull "___result_voidstar =
&___arg1;"))
has the advantage of not wasting time / space creating a new foreign
object and a copy, like *->My below does.
It also doesn't trigger the c-lambda bug, not that I have verified
carefully yet.
Members can easily be set up with a syntax like (My-x-set! (My->*
xoxo) #xdeadbeef) .
Is this approach correct?
Thanks Again
Paolo
Il giorno 14/dic/2015, alle ore 18:02, Marc Feeley <
feeley@iro.umontreal.ca> ha scritto:
There appears to be a bug in the FFI when using a c-lambda with
inline code that returns a foreign object. So for now you will have to define a C function that does the work and use the name of that function in the c-lambda. In other words:
(c-declare #<<c-declare-end
My indirect_My_star(My *ptr) { return *ptr; }
c-declare-end )
(define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))
Marc
On Dec 14, 2015, at 4:55 AM, Paolo Carlesi pcarlesi@gmail.com
wrote:
Hello,
I'm experiencing regular segfaults on OSX 10.9.5, with the sample
code shown below.
Tested with Gambit 4.8.1 + GCC 4.9 and with packaged Gambit 4.7.3 +
LLVM.
No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit
4.8.2.
Of course I may be doing something silly.
A simple struct, "My" is generated inside a c procedure, then passed
multiple times to another c-lambda procedure (*->My).
It's a simplified model of the code produced by a FFI SDL2 Library
I'm using.
The doc says that the foreign object (xoxo in the example) should
not be released while the scheme code is still referencing it.
I am seeing the refcount going wildly in the negative, one for each
call to *->My
The only way -- clumsy -- I have found to avoid this is to increment
the reference count with ___addref_rc ( not shown here ).
What's wrong here? Thanks!
LLDB output:
Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64) Process 48149 stopped
- thread #1: tid = 0x40e3c9, 0x000000010000770c
fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x000000010000770c fromlin`___release_rc + 28 fromlin`___release_rc + 28: -> 0x10000770c: movq %rax, (%rdx) 0x10000770f: movq %rdx, 0x8(%rax) 0x100007713: jmp 0x100010240 ; ___free_mem 0x100007718: nopl (%rax,%rax)
stack trace:
(lldb) bt
- thread #1: tid = 0x40e3c9, 0x000000010000770c
fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x000000010000770c fromlin`___release_rc + 28
frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9 frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497 frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255 frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43 frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20 frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378 frame #7: 0x0000000100004aa4 fromlin`___call + 372 frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262 frame #9: 0x00000001000063be fromlin`___setup + 3950 (lldb)
;; SAMPLE CODE
(c-declare #<<c-declare-end
typedef struct My { int r; } My;
c-declare-end )
(begin (c-define-type My (struct "My")) (c-define-type My* (pointer My (My*))) (c-define-type My*/nonnull (nonnull-pointer My (My*))) (c-define-type My*/release-rc (nonnull-pointer My (My*)
"___release_My")))
(begin (c-declare #<<c-declare-end static ___SCMOBJ ___release_My( void* ptr ) { ___EXT(___release_rc)( ptr ); return ___FIX(___NO_ERR); } c-declare-end )
(define alloc-My (c-lambda () My*/release-rc "___result_voidstar =
___EXT(___alloc_rc)( sizeof( struct My ));"))
(define *->My (c-lambda (My*/nonnull) My "___result_voidstar =
(My*)___arg1;"))
(define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result =
___arg1->r;"))
(define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void
"___arg1->r = ___arg2;")))
(define (evil) (let ((xoxo (alloc-My))) (My-r-set! xoxo #xff) (let loop ((c 1)) (begin (if (= 0 (remainder c 10000)) (begin (display c) (newline))) (*->My xoxo) (loop (+ 1 c))))))
(evil)
;;END CODE
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list