shared memory, perl, FreebSD 6

Anton Berezin tobez at tobez.org
Mon Nov 14 06:45:58 PST 2005


On Mon, Nov 14, 2005 at 01:29:13PM +0100, Heiko Weber wrote:
> Am Montag, 14. November 2005 09:58 schrieb Anton Berezin:
> > On Sun, Nov 13, 2005 at 12:55:20AM +0100, Heiko Weber wrote:
> > > I have problem using shared memory with perl. I tried p5-IPC-ShareLite:
> > >
> > > Segmentation fault (core dumped)
> > > *** Error code 139

[Mathieu, are you paying attention?  :-) ]

Ok.

The following patch should fix the problem with p5-IPC-ShareLite.  You
should cd /usr/ports/devel/p5-IPC-ShareLite ; make clean.  Then copy the
patch to files/patch-sharelite.c.  Then rebuild.

--- sharelite.c.orig	Mon Nov 14 15:37:08 2005
+++ sharelite.c	Mon Nov 14 15:37:41 2005
@@ -1,3 +1,7 @@
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -151,7 +155,7 @@ Node *_add_segment(Share *share) {
   Node *node;
   int  flags;
 
-  if ((node = (Node *) malloc(sizeof(Node))) == NULL) 
+  if ((node = (Node *) safemalloc(sizeof(Node))) == NULL) 
     return NULL; 
   node->next = NULL;
 
@@ -196,7 +200,7 @@ int _detach_segments(Node *node) {
   while(node != NULL) {
     next_node  = node->next;
     if (shmdt((char *) node->shmaddr) < 0) return -1;
-    free(node);
+    safefree(node);
     node = next_node;
   }
   return 0;             
@@ -329,7 +333,7 @@ int read_share(Share *share, char **data
   node   = share->head;
   left = length = node->shmaddr->length;
 
-  if ((pos = *data = (char *) malloc( length )) == NULL)
+  if ((pos = *data = (char *) safemalloc( length )) == NULL)
     return -1;
 
   while(left) {
@@ -379,7 +383,7 @@ again:
     segment_size = SHM_SEGMENT_SIZE; 
   }
 
-  if ((node = (Node *) malloc(sizeof(Node))) == NULL) 
+  if ((node = (Node *) safemalloc(sizeof(Node))) == NULL) 
     return NULL;
   if ((node->shmid = shmget(key, segment_size, flags)) < 0)
     return NULL;
@@ -387,7 +391,7 @@ again:
     return NULL;
   node->next = NULL;
 
-  if ((share = (Share *) malloc(sizeof(Share))) == NULL) 
+  if ((share = (Share *) safemalloc(sizeof(Share))) == NULL) 
     return NULL;
   share->key       = key;
   share->next_key  = key + 1;
@@ -460,7 +464,7 @@ int destroy_share (Share *share, int rmi
       return -1;
   }
 
-  free(share);
+  safefree(share);
   
   return 0;
 }


The problem is that by default perl is built with its own version of
malloc.  (The other solution would be to rebuild your perl with
-DWITHOUT_PERL_MALLOC, but that is not a particularly good solution in
general, since Perl malloc is heavily optimized to multiple
reallocations, while FreeBSD system malloc is not).

Normally, this is not a problem for Perl XS modules.  Normally, it is
not even a problem for Perl XS modules that are using 3rd-party
C or C++ libraries.  It is only a problem when the XS part (or one of
the libraries/objects it is using) uses system malloc and then passes
those pointers back to perl.  The whole thing becomes acutely unhappy
when it tries to free() stuff which was allocated using a different
malloc library.  Hence the coredump.

I have not looked at the other module you had a problem with, but I
won't be surprized to find a similar bug.

Hope this helps,
Cheers,
\Anton.
-- 
An undefined problem has an infinite number of solutions.
-- Robert A. Humphrey


More information about the freebsd-perl mailing list