I have received a request to modify the dl_next.xs code for the
specific needs that arise from embedding perl and running multiple
interpreters at a time.
While the patch by Gerd Knops (forwarded to me by Anno Siegel) would
be a handy short-term solution, I want to ask you, what would be the
appropriate *portable* one.
The problem is, according to Gerd, that with multiple interpreters
libraries are loaded more than once resulting in rld errors.
How is that addressed in the other dl_*.xs implementations? Is that
something we should let the Dynaloader take care of? Is that already
solved on other architectures?
I append the patch suggested by Gerd below. I ran the standard tests
on it and Tk/widget and have (as expected) no problem so far.
I realize the potential problem of using the absolute pathname to
identify an already loaded object. This must be addressed (if the
interpreters have different @INC paths, they could find the same
labrary in different places). But I'm not deep enough in the problem
to suggest a better way.
Please CC your answers to Gert and Anno, both included in the header.
Thanks,
andreas
--- ../../../perl5.001m.1-orig/ext/DynaLoader/dl_next.xs Tue Oct 18 17:28:25 1994
+++ dl_next.xs Sat Sep 2 15:13:46 1995
@@ -83,13 +83,34 @@
char * path;
int mode; /* mode is ignored */
{
+/*****new*******/
+ static char **dl_next_loaded=NULL;
+/***************/
int rld_success;
NXStream *nxerr = OpenError();
AV * av_resolve;
I32 i, psize;
char *result;
char **p;
-
+
+/*****new*******/
+ /*
+ Do not load what is already loaded!
+ */
+ if(dl_next_loaded)
+ {
+ p=dl_next_loaded;
+ while(*p)
+ {
+ if(!strcmp(*p,path))
+ {
+ return path;
+ }
+ p++;
+ }
+ }
+/***************/
+
av_resolve = GvAVn(gv_fetchpv(
"DynaLoader::dl_resolve_using", FALSE, SVt_PVAV));
psize = AvFILL(av_resolve) + 3;
@@ -104,6 +125,28 @@
safefree((char*) p);
if (rld_success) {
result = path;
+/*****new*******/
+ {
+ /* Memorize what is already loaded */
+ if(!dl_next_loaded)
+ {
+ dl_next_loaded=malloc(sizeof(char *));
+ dl_next_loaded[0]=NULL;
+ }
+ p=dl_next_loaded;
+ i=0;
+ while(*p)
+ {
+ p++;
+ i++;
+ }
+ dl_next_loaded=realloc(dl_next_loaded,(i+1)*sizeof(char
+*));
+ dl_next_loaded[i]=malloc(strlen(path)+1);
+ strcpy(dl_next_loaded[i],path);
+ dl_next_loaded[i+1]=NULL;
+ }
+/***************/
} else {
TransferError(nxerr);
result = (char*) 0;
specific needs that arise from embedding perl and running multiple
interpreters at a time.
While the patch by Gerd Knops (forwarded to me by Anno Siegel) would
be a handy short-term solution, I want to ask you, what would be the
appropriate *portable* one.
The problem is, according to Gerd, that with multiple interpreters
libraries are loaded more than once resulting in rld errors.
How is that addressed in the other dl_*.xs implementations? Is that
something we should let the Dynaloader take care of? Is that already
solved on other architectures?
I append the patch suggested by Gerd below. I ran the standard tests
on it and Tk/widget and have (as expected) no problem so far.
I realize the potential problem of using the absolute pathname to
identify an already loaded object. This must be addressed (if the
interpreters have different @INC paths, they could find the same
labrary in different places). But I'm not deep enough in the problem
to suggest a better way.
Please CC your answers to Gert and Anno, both included in the header.
Thanks,
andreas
--- ../../../perl5.001m.1-orig/ext/DynaLoader/dl_next.xs Tue Oct 18 17:28:25 1994
+++ dl_next.xs Sat Sep 2 15:13:46 1995
@@ -83,13 +83,34 @@
char * path;
int mode; /* mode is ignored */
{
+/*****new*******/
+ static char **dl_next_loaded=NULL;
+/***************/
int rld_success;
NXStream *nxerr = OpenError();
AV * av_resolve;
I32 i, psize;
char *result;
char **p;
-
+
+/*****new*******/
+ /*
+ Do not load what is already loaded!
+ */
+ if(dl_next_loaded)
+ {
+ p=dl_next_loaded;
+ while(*p)
+ {
+ if(!strcmp(*p,path))
+ {
+ return path;
+ }
+ p++;
+ }
+ }
+/***************/
+
av_resolve = GvAVn(gv_fetchpv(
"DynaLoader::dl_resolve_using", FALSE, SVt_PVAV));
psize = AvFILL(av_resolve) + 3;
@@ -104,6 +125,28 @@
safefree((char*) p);
if (rld_success) {
result = path;
+/*****new*******/
+ {
+ /* Memorize what is already loaded */
+ if(!dl_next_loaded)
+ {
+ dl_next_loaded=malloc(sizeof(char *));
+ dl_next_loaded[0]=NULL;
+ }
+ p=dl_next_loaded;
+ i=0;
+ while(*p)
+ {
+ p++;
+ i++;
+ }
+ dl_next_loaded=realloc(dl_next_loaded,(i+1)*sizeof(char
+*));
+ dl_next_loaded[i]=malloc(strlen(path)+1);
+ strcpy(dl_next_loaded[i],path);
+ dl_next_loaded[i+1]=NULL;
+ }
+/***************/
} else {
TransferError(nxerr);
result = (char*) 0;