Hi, I'm currently working on a Perl binding for the SILC client API. SILC (http://www.silcnet.org/) ist basically IRC with encryption. The work done so far is on Sourceforge at http://sourceforge.net/projects/silcpm. The Module is working for a small example script combining both Net::Client::Silc and Chatbot::Eliza into a simple bot. The version on Sourceforge basically works, but has a minor problem which I was unable to solve in the last couple of days. The SILC client API comes with a runtime loop (called silc_client_run()) which does all the event processing. The problem I have is that I want to use my own event loop (probably using Event.pm) to allow defining of own timed events, e.g. fetching and displaying an RSS feed. For this, the API provides a function called silc_client_run_once() which handles some events and returns.
The Problem I have is that when I trigger this myself from inside Perl space, the memory gets corrupted and the pointer to the structure which silc_client_run_once() takes as parameter gets invalid, thus crashing the whole module. A patch agains Net::SILC::Client to trigger this behaviour is apended to this post. Mostly, what is happening is that the Client.pm module (source at http://cvs.sourceforge.net/viewcvs.py/silcpm/net-silc-client/lib/Net/SILC/Client.pm?view=markup) does something like: while (1) { $self->silc_run_one(); select(undef, undef, undef, 0.10); } silc_run_one is a XS method defined in SILC.xs (source at http://cvs.sourceforge.net/viewcvs.py/silcpm/net-silc-client/SILC.xs?view=markup) which is defined as: void silc_run_one(self) SV* self CODE: silc_client_run_one_perl(self); and calls the silc_client_run_one_perl method in client_ops.c (source at http://cvs.sourceforge.net/viewcvs.py/silcpm/net-silc-client/client_ops.c?view=markup) which is defined as: void silc_client_run_one_perl(SV* self) { net_silc_client_data* environment = silc_get_environment_perl(self); printf("run one called %p\n", environment->client); if (environment != NULL) { silc_client_run_one(environment->client); } } silc_get_environment returns an environment pointer which is stored inside the self hash. It always returns a valid pointer. Running ./bin/tester.pl which is a simple example to test the module it outputs the following: Calling connect Silc init perl called run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 run one called 0x81679e0 Segmentation fault The output of a backtrace in gdb and a look with valgrind it at http://wiki.thiesen.org/page/Net_Silc. #11 0xb7af94d1 in silc_client_run_one (client=0x2) at client.c:227 Apparently, the environment->client pointer gets overwriten. As there is not happening very much in between and most of the stuff in the client lib is asynchronous, I'm pretty lost at this point and don't know what to do to get it worked out. This is my first XS module, maybe I'm making a wrong assertion about how this stuff should work and this is just a minor mistake, but it's driving me quite crazy at the moment. Any suggestions? Have fun, Marcus P.S.: to compile the module, you need the Silc Toolkit, which is something like the SILC library. Unfortunately, the Debian packages for them are completely broken, so you have to build it yourself. Index: client_ops.c =================================================================== RCS file: /cvsroot/silcpm/net-silc-client/client_ops.c,v retrieving revision 1.9 diff -u -p -r1.9 client_ops.c --- client_ops.c 27 Oct 2005 07:52:40 -0000 1.9 +++ client_ops.c 27 Oct 2005 11:22:51 -0000 @@ -941,8 +941,9 @@ void silc_init_perl(SV* self, char* nick /* comment the following line and uncomment one of the other event loops in Client::connect to test alternate runloops */ - + /* silc_client_run(client); + */ } void silc_client_run_one_perl(SV* self) { Index: lib/Net/SILC/Client.pm =================================================================== RCS file: /cvsroot/silcpm/net-silc-client/lib/Net/SILC/Client.pm,v retrieving revision 1.8 diff -u -p -r1.8 Client.pm --- lib/Net/SILC/Client.pm 26 Oct 2005 19:46:12 -0000 1.8 +++ lib/Net/SILC/Client.pm 27 Oct 2005 11:22:51 -0000 @@ -205,10 +205,10 @@ sub connect() { # Event this crashes, apparently Perl is freeing scalars in silcs address space (valgrind) -# while (1) { -# $self->silc_run_one(); -# select(undef, undef, undef, 0.10); -# } + while (1) { + $self->silc_run_one(); + select(undef, undef, undef, 0.10); + } }