chicken-users
[Top][All Lists]
Advanced

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

[Chicken-users] Safely holding on to a <procedure> reference in C


From: Naitik Shah
Subject: [Chicken-users] Safely holding on to a <procedure> reference in C
Date: Sun, 20 Feb 2011 20:55:24 -0800

Hi,

I'm experimenting with Chicken and libevent using the bind extension to build a event based webserver. I'm trying to figure out if there's a way to have C code hold on to a <procedure> in a GC safe manner. The implementation I have so far works for a few requests, but eventually fails. Based on what I've learned so far it seems like this is because the GC is either throwing away or moving the <procedure> making the pointer in C being held by libevent invalid. Is it possible to hold on to a <procedure> like this? Here's the code (also here: https://gist.github.com/2b3884461320db313188) :

(require-extension bind)

(foreign-declare #<<EOF
#include <event.h>
#include <evhttp.h>
EOF
)
(bind-opaque-type _evhttp_request (c-pointer "struct evhttp_request"))
(bind-opaque-type _evbuffer (c-pointer "struct evbuffer"))
(bind-opaque-type _evhttp (c-pointer "struct evhttp"))
(bind-opaque-type _event_base (c-pointer "struct event_base"))
(bind "___safe _event_base event_init();")
(bind "___safe void event_dispatch();")
(bind "___safe int event_dispatch();")
(bind "___safe _evbuffer evbuffer_new();")
(bind "___safe int evbuffer_add_printf(_evbuffer, const char*);")
(bind "___safe _evhttp evhttp_start(const char*, unsigned short);")
(bind "___safe void evhttp_free(_evhttp);")
(bind "___safe void evhttp_send_reply(_evhttp_request, int, const char*, _evbuffer);")
(bind "___safe void evhttp_set_gencb(_evhttp, void (*)(_evhttp_request, ___scheme_value), ___scheme_value);")

(display "evented loaded\n")

(define (hello-world-page req)
  (let ((buf (evbuffer_new)))
    (evbuffer_add_printf buf "hello world")
    (evhttp_send_reply req 200 "OK" buf)))

(define-external (request_handler (_evhttp_request req)
                                  (scheme-object handler))
  void
  (handler req))

(event_init)
(let ((httpd (evhttp_start "0.0.0.0" 8080)))
  (evhttp_set_gencb httpd #$request_handler hello-world-page)
  (event_dispatch)
  (evhttp_free httpd))

Here's the error after a few hundred requests:

address@hidden ~/Development/cc csc -o evented -levent evented.scm && ./evented
evented.c: In function ‘stub187’:
evented.c:66: warning: passing argument 2 of ‘evhttp_set_gencb’ from incompatible pointer type
evented.c:66: warning: passing argument 3 of ‘evhttp_set_gencb’ makes pointer from integer without a cast
evented.c: In function ‘stub104’:
evented.c:115: warning: format not a string literal and no format arguments
evented loaded

Error: call of non-procedure: #<invalid forwarded object>

        Call history:

        ##sys#gc
        g27
        ##sys#make-c-string
        g111112
        evented.scm:27: evhttp_send_reply
        ##sys#gc
        ##sys#make-c-string
        g27
        g171172
        evented.scm:32: handler         <--


Thanks for reading this far!

-Naitik

reply via email to

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