Mercurial > hg > nginx
annotate src/core/ngx_module.c @ 6383:85dea406e18f
Dynamic modules.
The auto/module script is extended to understand ngx_module_link=DYNAMIC.
When set, it links the module as a shared object rather than statically
into nginx binary. The module can later be loaded using the "load_module"
directive.
New auto/module parameter ngx_module_order allows to define module loading
order in complex cases. By default the order is set based on ngx_module_type.
3rd party modules can be compiled dynamically using the --add-dynamic-module
configure option, which will preset ngx_module_link to "DYNAMIC" before
calling the module config script.
Win32 support is rudimentary, and only works when using MinGW gcc (which
is able to handle exports/imports automatically).
In collaboration with Ruslan Ermilov.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 04 Feb 2016 20:25:29 +0300 |
parents | cf5e822cf470 |
children | 5fe617f38222 |
rev | line source |
---|---|
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
1 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
2 /* |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
3 * Copyright (C) Igor Sysoev |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
4 * Copyright (C) Maxim Dounin |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
5 * Copyright (C) Nginx, Inc. |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
6 */ |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
7 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
8 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
9 #include <ngx_config.h> |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
10 #include <ngx_core.h> |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
11 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
12 |
6383 | 13 #define NGX_MAX_DYNAMIC_MODULES 128 |
14 | |
15 | |
16 static ngx_uint_t ngx_module_index(ngx_cycle_t *cycle); | |
17 static ngx_uint_t ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, | |
18 ngx_uint_t index); | |
19 | |
20 | |
21 ngx_uint_t ngx_max_module; | |
22 static ngx_uint_t ngx_modules_n; | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
23 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
24 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
25 ngx_int_t |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
26 ngx_preinit_modules() |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
27 { |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
28 ngx_uint_t i; |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
29 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
30 ngx_max_module = 0; |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
31 for (i = 0; ngx_modules[i]; i++) { |
6383 | 32 ngx_modules[i]->index = i; |
33 ngx_modules[i]->name = ngx_module_names[i]; | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
34 } |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
35 |
6383 | 36 ngx_modules_n = i; |
37 ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES; | |
38 | |
39 return NGX_OK; | |
40 } | |
41 | |
42 | |
43 ngx_int_t | |
44 ngx_cycle_modules(ngx_cycle_t *cycle) | |
45 { | |
46 /* | |
47 * create a list of modules to be used for this cycle, | |
48 * copy static modules to it | |
49 */ | |
50 | |
51 cycle->modules = ngx_pcalloc(cycle->pool, (ngx_max_module + 1) | |
52 * sizeof(ngx_module_t *)); | |
53 if (cycle->modules == NULL) { | |
54 return NGX_ERROR; | |
55 } | |
56 | |
57 ngx_memcpy(cycle->modules, ngx_modules, | |
58 ngx_modules_n * sizeof(ngx_module_t *)); | |
59 | |
60 cycle->modules_n = ngx_modules_n; | |
61 | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
62 return NGX_OK; |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
63 } |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
64 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
65 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
66 ngx_int_t |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
67 ngx_init_modules(ngx_cycle_t *cycle) |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
68 { |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
69 ngx_uint_t i; |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
70 |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
71 for (i = 0; cycle->modules[i]; i++) { |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
72 if (cycle->modules[i]->init_module) { |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
73 if (cycle->modules[i]->init_module(cycle) != NGX_OK) { |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
74 return NGX_ERROR; |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
75 } |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
76 } |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
77 } |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
78 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
79 return NGX_OK; |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
80 } |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
81 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
82 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
83 ngx_int_t |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
84 ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type) |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
85 { |
6383 | 86 ngx_uint_t i, next, max; |
87 ngx_module_t *module; | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
88 |
6383 | 89 next = 0; |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
90 max = 0; |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
91 |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
92 /* count appropriate modules, set up their indices */ |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
93 |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
94 for (i = 0; cycle->modules[i]; i++) { |
6383 | 95 module = cycle->modules[i]; |
96 | |
97 if (module->type != type) { | |
98 continue; | |
99 } | |
100 | |
101 if (module->ctx_index != NGX_MODULE_UNSET_INDEX) { | |
102 | |
103 /* if ctx_index was assigned, preserve it */ | |
104 | |
105 if (module->ctx_index > max) { | |
106 max = module->ctx_index; | |
107 } | |
108 | |
109 if (module->ctx_index == next) { | |
110 next++; | |
111 } | |
112 | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
113 continue; |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
114 } |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
115 |
6383 | 116 /* search for some free index */ |
117 | |
118 module->ctx_index = ngx_module_ctx_index(cycle, type, next); | |
119 | |
120 if (module->ctx_index > max) { | |
121 max = module->ctx_index; | |
122 } | |
123 | |
124 next = module->ctx_index + 1; | |
125 } | |
126 | |
127 /* | |
128 * make sure the number returned is big enough for previous | |
129 * cycle as well, else there will be problems if the number | |
130 * will be stored in a global variable (as it's used to be) | |
131 * and we'll have to roll back to the previous cycle | |
132 */ | |
133 | |
134 if (cycle->old_cycle && cycle->old_cycle->modules) { | |
135 | |
136 for (i = 0; cycle->old_cycle->modules[i]; i++) { | |
137 module = cycle->old_cycle->modules[i]; | |
138 | |
139 if (module->type != type) { | |
140 continue; | |
141 } | |
142 | |
143 if (module->ctx_index > max) { | |
144 max = module->ctx_index; | |
145 } | |
146 } | |
147 } | |
148 | |
149 /* prevent loading of additional modules */ | |
150 | |
151 cycle->modules_used = 1; | |
152 | |
153 return max + 1; | |
154 } | |
155 | |
156 | |
157 ngx_int_t | |
158 ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, ngx_module_t *module, | |
159 char **order) | |
160 { | |
161 void *rv; | |
162 ngx_uint_t i, m, before; | |
163 ngx_core_module_t *core_module; | |
164 | |
165 if (cf->cycle->modules_n >= ngx_max_module) { | |
166 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
167 "too many modules loaded"); | |
168 return NGX_ERROR; | |
169 } | |
170 | |
171 if (module->version != nginx_version) { | |
172 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
173 "module \"%V\" version %ui instead of %ui", | |
174 file, module->version, nginx_version); | |
175 return NGX_ERROR; | |
176 } | |
177 | |
178 if (ngx_strcmp(module->signature, NGX_MODULE_SIGNATURE) != 0) { | |
179 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
180 "module \"%V\" is not binary compatible", | |
181 file); | |
182 return NGX_ERROR; | |
183 } | |
184 | |
185 for (m = 0; cf->cycle->modules[m]; m++) { | |
186 if (ngx_strcmp(cf->cycle->modules[m]->name, module->name) == 0) { | |
187 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
188 "module \"%s\" is already loaded", | |
189 module->name); | |
190 return NGX_ERROR; | |
191 } | |
192 } | |
193 | |
194 /* | |
195 * if the module wasn't previously loaded, assign an index | |
196 */ | |
197 | |
198 if (module->index == NGX_MODULE_UNSET_INDEX) { | |
199 module->index = ngx_module_index(cf->cycle); | |
200 | |
201 if (module->index >= ngx_max_module) { | |
202 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
203 "too many modules loaded"); | |
204 return NGX_ERROR; | |
205 } | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
206 } |
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
207 |
6383 | 208 /* |
209 * put the module into the cycle->modules array | |
210 */ | |
211 | |
212 before = cf->cycle->modules_n; | |
213 | |
214 if (order) { | |
215 for (i = 0; order[i]; i++) { | |
216 if (ngx_strcmp(order[i], module->name) == 0) { | |
217 i++; | |
218 break; | |
219 } | |
220 } | |
221 | |
222 for ( /* void */ ; order[i]; i++) { | |
223 | |
224 #if 0 | |
225 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, | |
226 "module: %s before %s", | |
227 module->name, order[i]); | |
228 #endif | |
229 | |
230 for (m = 0; m < before; m++) { | |
231 if (ngx_strcmp(cf->cycle->modules[m]->name, order[i]) == 0) { | |
232 | |
233 ngx_log_debug3(NGX_LOG_DEBUG_CORE, cf->log, 0, | |
234 "module: %s before %s:%i", | |
235 module->name, order[i], m); | |
236 | |
237 before = m; | |
238 break; | |
239 } | |
240 } | |
241 } | |
242 } | |
243 | |
244 /* put the module before modules[before] */ | |
245 | |
246 if (before != cf->cycle->modules_n) { | |
247 ngx_memmove(&cf->cycle->modules[before + 1], | |
248 &cf->cycle->modules[before], | |
249 (cf->cycle->modules_n - before) * sizeof(ngx_module_t *)); | |
250 } | |
251 | |
252 cf->cycle->modules[before] = module; | |
253 cf->cycle->modules_n++; | |
254 | |
255 if (module->type == NGX_CORE_MODULE) { | |
256 | |
257 /* | |
258 * we are smart enough to initialize core modules; | |
259 * other modules are expected to be loaded before | |
260 * initialization - e.g., http modules must be loaded | |
261 * before http{} block | |
262 */ | |
263 | |
264 core_module = module->ctx; | |
265 | |
266 if (core_module->create_conf) { | |
267 rv = core_module->create_conf(cf->cycle); | |
268 if (rv == NULL) { | |
269 return NGX_ERROR; | |
270 } | |
271 | |
272 cf->cycle->conf_ctx[module->index] = rv; | |
273 } | |
274 } | |
275 | |
276 return NGX_OK; | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
277 } |
6383 | 278 |
279 | |
280 static ngx_uint_t | |
281 ngx_module_index(ngx_cycle_t *cycle) | |
282 { | |
283 ngx_uint_t i, index; | |
284 ngx_module_t *module; | |
285 | |
286 index = 0; | |
287 | |
288 again: | |
289 | |
290 /* find an unused index */ | |
291 | |
292 for (i = 0; cycle->modules[i]; i++) { | |
293 module = cycle->modules[i]; | |
294 | |
295 if (module->index == index) { | |
296 index++; | |
297 goto again; | |
298 } | |
299 } | |
300 | |
301 /* check previous cycle */ | |
302 | |
303 if (cycle->old_cycle && cycle->old_cycle->modules) { | |
304 | |
305 for (i = 0; cycle->old_cycle->modules[i]; i++) { | |
306 module = cycle->old_cycle->modules[i]; | |
307 | |
308 if (module->index == index) { | |
309 index++; | |
310 goto again; | |
311 } | |
312 } | |
313 } | |
314 | |
315 return index; | |
316 } | |
317 | |
318 | |
319 static ngx_uint_t | |
320 ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, ngx_uint_t index) | |
321 { | |
322 ngx_uint_t i; | |
323 ngx_module_t *module; | |
324 | |
325 again: | |
326 | |
327 /* find an unused ctx_index */ | |
328 | |
329 for (i = 0; cycle->modules[i]; i++) { | |
330 module = cycle->modules[i]; | |
331 | |
332 if (module->type != type) { | |
333 continue; | |
334 } | |
335 | |
336 if (module->ctx_index == index) { | |
337 index++; | |
338 goto again; | |
339 } | |
340 } | |
341 | |
342 /* check previous cycle */ | |
343 | |
344 if (cycle->old_cycle && cycle->old_cycle->modules) { | |
345 | |
346 for (i = 0; cycle->old_cycle->modules[i]; i++) { | |
347 module = cycle->old_cycle->modules[i]; | |
348 | |
349 if (module->type != type) { | |
350 continue; | |
351 } | |
352 | |
353 if (module->ctx_index == index) { | |
354 index++; | |
355 goto again; | |
356 } | |
357 } | |
358 } | |
359 | |
360 return index; | |
361 } |