This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate change #12626 from maintperl;
[perl5.git] / ext / DynaLoader / dlutils.c
CommitLineData
a0d0e21e
LW
1/* dlutils.c - handy functions and definitions for dl_*.xs files
2 *
3 * Currently this file is simply #included into dl_*.xs/.c files.
4 * It should really be split into a dlutils.h and dlutils.c
5 *
abb9e9dc
GS
6 * Modified:
7 * 29th Feburary 2000 - Alan Burlison: Added functionality to close dlopen'd
8 * files when the interpreter exits
a0d0e21e
LW
9 */
10
cdc73a10 11#define MY_CXT_KEY "DynaLoader_guts"
a0d0e21e 12
cdc73a10
JH
13typedef struct {
14 char * x_dl_last_error; /* pointer to allocated memory for
15 last error message */
16 int x_dl_nonlazy; /* flag for immediate rather than lazy
17 linking (spots unresolved symbol) */
18#ifdef DL_LOADONCEONLY
19 HV * x_dl_loaded_files; /* only needed on a few systems */
20#endif
21#ifdef DL_CXT_EXTRA
22 my_cxtx_t x_dl_cxtx; /* extra platform-specific data */
23#endif
24#ifdef DEBUGGING
25 int x_dl_debug; /* value copied from $DynaLoader::dl_debug */
26#endif
27} my_cxt_t;
28
29/* XXX most of this is boilerplate code that should abstracted further into
30 * macros and exposed via XSUB.h */
31
32#if defined(USE_ITHREADS)
33
34#define dMY_CXT_SV \
35 SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \
36 sizeof(MY_CXT_KEY)-1, TRUE)
37
38/* we allocate my_cxt in a Perl SV so that it will be released when
39 * the interpreter goes away */
40#define dMY_CXT_INIT \
41 dMY_CXT_SV; \
42 /* newSV() allocates one more than needed */ \
43 my_cxt_t *my_cxt = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1)); \
44 Zero(my_cxt, 1, my_cxt_t); \
45 sv_setuv(my_cxt_sv, (UV)my_cxt);
46
47#define dMY_CXT \
48 dMY_CXT_SV; \
49 my_cxt_t *my_cxt = (my_cxt_t*)SvUV(my_cxt_sv)
50
51#define dl_last_error (my_cxt->x_dl_last_error)
52#define dl_nonlazy (my_cxt->x_dl_nonlazy)
53#ifdef DL_LOADONCEONLY
54#define dl_loaded_files (my_cxt->x_dl_loaded_files)
55#endif
56#ifdef DL_CXT_EXTRA
57#define dl_cxtx (my_cxt->x_dl_cxtx)
58#endif
59#ifdef DEBUGGING
60#define dl_debug (my_cxt->x_dl_debug)
61#endif
62
63#else /* USE_ITHREADS */
a0d0e21e 64
cdc73a10 65static my_cxt_t my_cxt;
8e07c86e 66
cdc73a10
JH
67#define dMY_CXT_SV dNOOP
68#define dMY_CXT_INIT dNOOP
69#define dMY_CXT dNOOP
70
71#define dl_last_error (my_cxt.x_dl_last_error)
72#define dl_nonlazy (my_cxt.x_dl_nonlazy)
8e07c86e 73#ifdef DL_LOADONCEONLY
cdc73a10
JH
74#define dl_loaded_files (my_cxt.x_dl_loaded_files)
75#endif
76#ifdef DL_CXT_EXTRA
77#define dl_cxtx (my_cxt.x_dl_cxtx)
8e07c86e 78#endif
cdc73a10
JH
79#ifdef DEBUGGING
80#define dl_debug (my_cxt.x_dl_debug)
81#endif
82
83#endif /* !defined(USE_ITHREADS) */
a0d0e21e
LW
84
85
86#ifdef DEBUGGING
cdc73a10
JH
87#define DLDEBUG(level,code) \
88 STMT_START { \
89 dMY_CXT; \
90 if (dl_debug>=level) { code; } \
91 } STMT_END
a0d0e21e 92#else
cdc73a10 93#define DLDEBUG(level,code) NOOP
a0d0e21e
LW
94#endif
95
c6c619a9 96#ifdef DL_UNLOAD_ALL_AT_EXIT
abb9e9dc
GS
97/* Close all dlopen'd files */
98static void
acfe0abc 99dl_unload_all_files(pTHX_ void *unused)
abb9e9dc
GS
100{
101 CV *sub;
102 AV *dl_librefs;
103 SV *dl_libref;
104
105 if ((sub = get_cv("DynaLoader::dl_unload_file", FALSE)) != NULL) {
106 dl_librefs = get_av("DynaLoader::dl_librefs", FALSE);
107 while ((dl_libref = av_pop(dl_librefs)) != &PL_sv_undef) {
108 dSP;
109 ENTER;
110 SAVETMPS;
111 PUSHMARK(SP);
112 XPUSHs(sv_2mortal(dl_libref));
113 PUTBACK;
22851543 114 call_sv((SV*)sub, G_DISCARD | G_NODEBUG);
abb9e9dc
GS
115 FREETMPS;
116 LEAVE;
117 }
118 }
119}
c6c619a9 120#endif
abb9e9dc 121
a0d0e21e 122static void
acfe0abc 123dl_generic_private_init(pTHX) /* called by dl_*.xs dl_private_init() */
a0d0e21e 124{
8e07c86e 125 char *perl_dl_nonlazy;
cdc73a10
JH
126 dMY_CXT_INIT;
127
128 dl_last_error = NULL;
129 dl_nonlazy = 0;
130#ifdef DL_LOADONCEONLY
131 dl_loaded_files = Nullhv;
132#endif
a0d0e21e 133#ifdef DEBUGGING
cdc73a10
JH
134 {
135 SV *sv = get_sv("DynaLoader::dl_debug", 0);
136 dl_debug = sv ? SvIV(sv) : 0;
137 }
8e07c86e
AD
138#endif
139 if ( (perl_dl_nonlazy = getenv("PERL_DL_NONLAZY")) != NULL )
140 dl_nonlazy = atoi(perl_dl_nonlazy);
141 if (dl_nonlazy)
bf49b057 142 DLDEBUG(1,PerlIO_printf(Perl_debug_log, "DynaLoader bind mode is 'non-lazy'\n"));
8e07c86e
AD
143#ifdef DL_LOADONCEONLY
144 if (!dl_loaded_files)
145 dl_loaded_files = newHV(); /* provide cache for dl_*.xs if needed */
a0d0e21e 146#endif
23d2500b 147#ifdef DL_UNLOAD_ALL_AT_EXIT
abb9e9dc 148 call_atexit(&dl_unload_all_files, (void*)0);
23d2500b 149#endif
a0d0e21e
LW
150}
151
152
cdc73a10 153/* SaveError() takes printf style args and saves the result in dl_last_error */
a0d0e21e 154static void
acfe0abc 155SaveError(pTHX_ char* pat, ...)
a0d0e21e 156{
cdc73a10 157 dMY_CXT;
a0d0e21e 158 va_list args;
a6c40364 159 SV *msv;
a0d0e21e 160 char *message;
a6c40364 161 STRLEN len;
a0d0e21e 162
8e07c86e 163 /* This code is based on croak/warn, see mess() in util.c */
a0d0e21e 164
a0d0e21e 165 va_start(args, pat);
5a844595 166 msv = vmess(pat, &args);
a0d0e21e
LW
167 va_end(args);
168
a6c40364
GS
169 message = SvPV(msv,len);
170 len++; /* include terminating null char */
a0d0e21e
LW
171
172 /* Allocate some memory for the error message */
cdc73a10
JH
173 if (dl_last_error)
174 dl_last_error = (char*)saferealloc(dl_last_error, len);
a0d0e21e 175 else
cdc73a10 176 dl_last_error = (char*)safemalloc(len);
a0d0e21e 177
cdc73a10
JH
178 /* Copy message into dl_last_error (including terminating null char) */
179 strncpy(dl_last_error, message, len) ;
180 DLDEBUG(2,PerlIO_printf(Perl_debug_log, "DynaLoader: stored error msg '%s'\n",dl_last_error));
a0d0e21e
LW
181}
182