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);
+    }

 }

Reply via email to