chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] #<invalid forwarded object> using FFI callback


From: .alyn.post.
Subject: Re: [Chicken-users] #<invalid forwarded object> using FFI callback
Date: Thu, 19 Dec 2013 15:38:46 -0701

Good day pulijzer.

I have not.  My best guess currently is that my call to make-string
returns a scheme object back to C.  I then make another call to
make-string, and the GC doesn't (so far as I understand it) have a
reference to that first make-string.  If any of these intermediate
make-string calls triggers a GC, I'll be left with a reference that
was garbage collected.  (I'm further given to understand I get a
categorically distinct GC (a minor GC?) that doesn't longjmp,
because I'm calling in to Scheme from non-reentrant C code.  Which
may or may not matter...)

If the GC takes care to mark every object passed to C as a root
pointer this wouldn't happen.  I'm neither sure this is what is
causing my invalid forwarded object problem nor whether or not
Chicken does object marking around the C FFI boundary.

on IRC I was advised to break up my call to C in to smaller pieces
so I wasn't holding any/as many scheme objects.  I haven't revisited
this code since receiving that advice as I find it vaguely
unsuitable and plan to review the relevant parts of the FFI
interface for a more informed fix--as this becomes a crisis rather
than an intermittent problem.

I'm embarrassed to report this code fires during a consistent point
during initialization of my code, and I set a high-enough initial heap
to not trigger a GC.  That initial heap size is there for other
reasons--but it helped make this problem go away for me too.

-a

On Thu, Dec 19, 2013 at 09:15:21PM +0100, pluijzer . wrote:
>    Hello Alyn,
> 
>    Did you find a solution to this problem? I seem to suffer a similar
>    problem.
> 
>    thanks,
>    Pluijzer
> 
>    2013/12/8 .alyn.post. <address@hidden>
> 
>      Greetings,
> 
>      I'm encountering the following error message inside a callback using
>      Chicken's FFI interface:
> 
>      Error: (cdr) bad argument type: #<invalid forwarded object>
> 
>      * * * * Call history:
> 
>      * * * * pwent.scm:100: loop
>      * * * * pwent.scm:56: ##sys#gc
>      * * * * pwent.scm:56: g42
>      * * * * pwent.scm:24: make-string
>      * * * * pwent.scm:24: make-string
>      * * * * pwent.scm:24: make-string
>      * * * * pwent.scm:24: make-string
>      * * * * pwent.scm:50: clist-append!
>      * * * * pwent.scm:100: loop
>      * * * * pwent.scm:56: ##sys#gc
>      * * * * pwent.scm:56: g42
>      * * * * pwent.scm:24: make-string
>      * * * * pwent.scm:24: make-string
>      * * * * pwent.scm:24: make-string
>      * * * * pwent.scm:24: make-string
>      * * * * pwent.scm:50: clist-append! * * * * * * <--
> 
>      What seems to be happening is that I'm running out of (stack?) memory
>      while inside/around a C thunk. *I cannot seem to avoid this message by
>      modifying the nursery, either from csc -nursery or from -:s.
> 
>      I have only a topical grasp of Chicken's FFI, so I suspect I'm simply
>      doing something ill-advised, though I would appreciate advice on how
>      to approach my problem:
> 
>      I'm trying to read /etc/passwd using getpwent(3) and store each
>      record returned in a scheme list. *(My particular /etc/passwd file
>      contains <100 elements, the above error happens near the end of the
>      call.) *I'm marshalling records using two callbacks: one to create the
>      memory for string data, and one to append each record to the list.
> 
>      May I have feedback on the pattern I'm using here to marshall data?
>      And a suggestion on how to avoid invalid forward objects while
>      reading large but disjoint data from C? *I'm at a loss as to why
>      exactly I'm getting the above message, and it well could be incorrect
>      code on my part. *Do my multiple calls to _make_string from C,
>      below, cause the GC to loose track of my string pointers? *Something
>      else?
> 
>      <++> csc -o pwent pwent.scm && ./pwent
>      (use extras)
> 
>      ; a circular list (where we track the
>      ; head and tail) with a dummy head.
>      ;
>      (define (make-clist)
>      * (let ((head (list #f)))
>      * * (cons head head)))
> 
>      ; O(1) list append.
>      ;
>      (define (clist-append! d v)
>      * (let ((l (list v)))
>      * * (set-cdr! (cdr d) l)
>      * * (set-cdr! d l)))
> 
>      ; return proper list
>      ;
>      (define (clist->list d)
>      * (cdr (car d)))
> 
>      ; allocate a scheme string available in C.
>      ;
>      (define-external
>      * (_make_string (size_t n)) scheme-object
>      * * (make-string n))
> 
>      (declare (foreign-declare #<<EOF
>      #include <sys/types.h>
>      #include <string.h>
>      #include <pwd.h>
>      EOF
>      ))
> 
>      (define (getpwent)
>      * ; append! each pwent record to our record list.
>      * ;
>      * (define-external
>      * * (_getpwent_cb (scheme-object clist)
>      * * * * * * * * * (scheme-object user)
>      * * * * * * * * * (scheme-object passwd)
>      * * * * * * * * * (scheme-object uid)
>      * * * * * * * * * (scheme-object gid)
>      * * * * * * * * * (scheme-object home)
>      * * * * * * * * * (scheme-object shell)) void
>      * * * (let ((pwent `((user * . ,user)
>      * * * * * * * * * * *(passwd . ,passwd)
>      * * * * * * * * * * *(uid * *. ,uid)
>      * * * * * * * * * * *(gid * *. ,gid)
>      * * * * * * * * * * *(home * . ,home)
>      * * * * * * * * * * *(shell *. ,shell))))
>      * * * * (clist-append! clist pwent)))
> 
>      * ; retrieve the next pwent record and marshall it
>      * ; in to scheme.
>      * ;
>      * (define _getpwent
>      * * (foreign-safe-lambda* bool ((scheme-object clist)) #<<EOF
>      * * struct passwd *pw;
>      * * C_word shell, dir, passwd, name;
>      * * size_t n;
> 
>      * * pw = getpwent();
> 
>      * * if(!pw) {
>      * * * endpwent();
>      * * * C_return(0);
>      * * }
> 
>      * * n = strlen(pw->pw_name);
>      * * name = _make_string(n);
>      * * C_memcpy(C_c_string(name), pw->pw_name, n);
> 
>      * * n = strlen(pw->pw_passwd);
>      * * passwd = _make_string(n);
>      * * C_memcpy(C_c_string(passwd), pw->pw_passwd, n);
> 
>      * * n = strlen(pw->pw_dir);
>      * * dir = _make_string(n);
>      * * C_memcpy(C_c_string(dir), pw->pw_dir, n);
> 
>      * * n = strlen(pw->pw_shell);
>      * * shell = _make_string(n);
>      * * C_memcpy(C_c_string(shell), pw->pw_shell, n);
> 
>      * * _getpwent_cb(clist,
>      * * * * * * * * *name,
>      * * * * * * * * *passwd,
>      * * * * * * * * *C_fix(pw->pw_uid),
>      * * * * * * * * *C_fix(pw->pw_gid),
>      * * * * * * * * *dir,
>      * * * * * * * * *shell);
>      * * C_return(1);
>      EOF
>      ))
> 
>      * ; loop ever every entry in pwent and append
>      * ; it to our list.
>      * ;
>      * (let loop ((clist (make-clist)))
>      * * (if (_getpwent clist)
>      * * * * (loop clist)
>      * * * * (clist->list clist))))
> 
>      (pretty-print (getpwent))
>      <-->
> 
>      Thank you,
> 
>      -a
> 
>      $ csc -version
>      (c) 2008-2013, The Chicken Team
>      (c) 2000-2007, Felix L. Winkelmann
>      Version 4.8.0.5 (stability/4.8.0) (rev 5bd53ac)
>      openbsd-unix-gnu-x86 [ manyargs dload ptables ]
>      compiled 2013-10-03 on aeryn.xorinia.dim (Darwin)
>      --
>      my personal website: [2]http://c0redump.org/
> 
>      _______________________________________________
>      Chicken-users mailing list
>      address@hidden
>      [4]https://lists.nongnu.org/mailman/listinfo/chicken-users
> 
> References
> 
>    Visible links
>    1. mailto:address@hidden
>    2. http://c0redump.org/
>    3. mailto:address@hidden
>    4. https://lists.nongnu.org/mailman/listinfo/chicken-users

> _______________________________________________
> Chicken-users mailing list
> address@hidden
> https://lists.nongnu.org/mailman/listinfo/chicken-users


-- 
my personal website: http://c0redump.org/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]