Mercurial > hg > nginx-quic
comparison src/http/modules/perl/ngx_http_perl_module.c @ 872:1c4a5b3f9110
Axe several perl interpreter instances: they may be useful in currently
unsupported threaded environment, but now they complicate code:
*) perl_clone() requires at least duplicating nginx stash;
*) the multiplicity requires to re-evalute all precompiled subroutines
and nginx stash in new interpreter context.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 26 Nov 2006 14:35:27 +0000 |
parents | a980f66c04fb |
children | f92ad15c2db1 |
comparison
equal
deleted
inserted
replaced
871:a980f66c04fb | 872:1c4a5b3f9110 |
---|---|
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 #include <ngx_http_perl_module.h> | 10 #include <ngx_http_perl_module.h> |
11 | 11 |
12 | 12 |
13 typedef struct { | 13 typedef struct { |
14 PerlInterpreter **free_perls; | |
15 ngx_uint_t interp; | |
16 ngx_uint_t nalloc; | |
17 ngx_uint_t interp_max; | |
18 | |
19 PerlInterpreter *perl; | 14 PerlInterpreter *perl; |
20 ngx_str_t modules; | 15 ngx_str_t modules; |
21 ngx_array_t requires; | 16 ngx_array_t requires; |
22 } ngx_http_perl_main_conf_t; | 17 } ngx_http_perl_main_conf_t; |
23 | 18 |
43 #if (NGX_HTTP_SSI) | 38 #if (NGX_HTTP_SSI) |
44 static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r, | 39 static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r, |
45 ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params); | 40 ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params); |
46 #endif | 41 #endif |
47 | 42 |
48 static ngx_int_t | |
49 ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf, | |
50 PerlInterpreter **perl, ngx_log_t *log); | |
51 static ngx_inline void | |
52 ngx_http_perl_free_interpreter(ngx_http_perl_main_conf_t *pmcf, | |
53 PerlInterpreter *perl); | |
54 static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf, | 43 static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf, |
55 ngx_http_perl_main_conf_t *pmcf); | 44 ngx_http_perl_main_conf_t *pmcf); |
56 static PerlInterpreter * | 45 static PerlInterpreter * |
57 ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf, | 46 ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf, |
58 ngx_log_t *log); | 47 ngx_log_t *log); |
70 void *child); | 59 void *child); |
71 static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, | 60 static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, |
72 void *conf); | 61 void *conf); |
73 static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 62 static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
74 static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 63 static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
75 static char *ngx_http_perl_interp_max_unsupported(ngx_conf_t *cf, void *post, | 64 static void ngx_http_perl_cleanup_sv(void *data); |
76 void *data); | 65 |
77 #if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY) | 66 #if (NGX_HAVE_PERL_MULTIPLICITY) |
78 static void ngx_http_perl_cleanup_perl(void *data); | 67 static void ngx_http_perl_cleanup_perl(void *data); |
79 #endif | 68 #endif |
80 static void ngx_http_perl_cleanup_sv(void *data); | |
81 | |
82 | |
83 static ngx_conf_post_handler_pt ngx_http_perl_interp_max_p = | |
84 ngx_http_perl_interp_max_unsupported; | |
85 | 69 |
86 | 70 |
87 static ngx_command_t ngx_http_perl_commands[] = { | 71 static ngx_command_t ngx_http_perl_commands[] = { |
88 | 72 |
89 { ngx_string("perl_modules"), | 73 { ngx_string("perl_modules"), |
97 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | 81 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, |
98 ngx_http_perl_require, | 82 ngx_http_perl_require, |
99 NGX_HTTP_MAIN_CONF_OFFSET, | 83 NGX_HTTP_MAIN_CONF_OFFSET, |
100 0, | 84 0, |
101 NULL }, | 85 NULL }, |
102 | |
103 { ngx_string("perl_interp_max"), | |
104 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | |
105 ngx_conf_set_num_slot, | |
106 NGX_HTTP_MAIN_CONF_OFFSET, | |
107 offsetof(ngx_http_perl_main_conf_t, interp_max), | |
108 &ngx_http_perl_interp_max_p }, | |
109 | 86 |
110 { ngx_string("perl"), | 87 { ngx_string("perl"), |
111 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 88 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
112 ngx_http_perl, | 89 ngx_http_perl, |
113 NGX_HTTP_LOC_CONF_OFFSET, | 90 NGX_HTTP_LOC_CONF_OFFSET, |
227 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); | 204 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); |
228 } | 205 } |
229 | 206 |
230 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); | 207 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); |
231 | 208 |
232 rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log); | |
233 | |
234 if (rc != NGX_OK) { | |
235 ngx_http_finalize_request(r, rc); | |
236 return; | |
237 } | |
238 | |
239 { | 209 { |
240 | 210 |
241 dTHXa(ctx->perl); | 211 dTHXa(pmcf->perl); |
242 | 212 |
243 if (ctx->next == NULL) { | 213 if (ctx->next == NULL) { |
244 plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module); | 214 plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module); |
245 sub = plcf->sub; | 215 sub = plcf->sub; |
246 handler = &plcf->handler; | 216 handler = &plcf->handler; |
253 | 223 |
254 rc = ngx_http_perl_call_handler(aTHX_ r, sub, NULL, handler, NULL); | 224 rc = ngx_http_perl_call_handler(aTHX_ r, sub, NULL, handler, NULL); |
255 | 225 |
256 } | 226 } |
257 | 227 |
258 ngx_http_perl_free_interpreter(pmcf, ctx->perl); | |
259 | |
260 if (rc > 600) { | 228 if (rc > 600) { |
261 rc = NGX_OK; | 229 rc = NGX_OK; |
262 } | 230 } |
263 | 231 |
264 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 232 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
298 uintptr_t data) | 266 uintptr_t data) |
299 { | 267 { |
300 ngx_http_perl_variable_t *pv = (ngx_http_perl_variable_t *) data; | 268 ngx_http_perl_variable_t *pv = (ngx_http_perl_variable_t *) data; |
301 | 269 |
302 ngx_int_t rc; | 270 ngx_int_t rc; |
303 ngx_uint_t recursive; | |
304 ngx_str_t value; | 271 ngx_str_t value; |
305 ngx_http_perl_ctx_t *ctx; | 272 ngx_http_perl_ctx_t *ctx; |
306 ngx_http_perl_main_conf_t *pmcf; | 273 ngx_http_perl_main_conf_t *pmcf; |
307 | 274 |
308 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 275 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
315 if (ctx == NULL) { | 282 if (ctx == NULL) { |
316 return NGX_ERROR; | 283 return NGX_ERROR; |
317 } | 284 } |
318 | 285 |
319 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); | 286 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); |
320 | 287 } |
321 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); | 288 |
322 | 289 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); |
323 rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, | |
324 r->connection->log); | |
325 | |
326 if (rc != NGX_OK) { | |
327 return rc; | |
328 } | |
329 | |
330 recursive = 0; | |
331 | |
332 } else { | |
333 pmcf = NULL; | |
334 recursive = 1; | |
335 } | |
336 | 290 |
337 value.data = NULL; | 291 value.data = NULL; |
338 | 292 |
339 { | 293 { |
340 | 294 |
341 dTHXa(ctx->perl); | 295 dTHXa(pmcf->perl); |
342 | 296 |
343 rc = ngx_http_perl_call_handler(aTHX_ r, pv->sub, NULL, | 297 rc = ngx_http_perl_call_handler(aTHX_ r, pv->sub, NULL, |
344 &pv->handler, &value); | 298 &pv->handler, &value); |
345 | 299 |
346 } | |
347 | |
348 if (recursive == 0) { | |
349 ngx_http_perl_free_interpreter(pmcf, ctx->perl); | |
350 } | 300 } |
351 | 301 |
352 if (value.data) { | 302 if (value.data) { |
353 v->len = value.len; | 303 v->len = value.len; |
354 v->valid = 1; | 304 v->valid = 1; |
383 ngx_http_perl_main_conf_t *pmcf; | 333 ngx_http_perl_main_conf_t *pmcf; |
384 | 334 |
385 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 335 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
386 "perl ssi handler"); | 336 "perl ssi handler"); |
387 | 337 |
388 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); | |
389 | |
390 ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); | 338 ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); |
391 | 339 |
392 if (ctx == NULL) { | 340 if (ctx == NULL) { |
393 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t)); | 341 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t)); |
394 if (ctx == NULL) { | 342 if (ctx == NULL) { |
396 } | 344 } |
397 | 345 |
398 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); | 346 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); |
399 } | 347 } |
400 | 348 |
401 rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log); | 349 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); |
402 | |
403 if (rc != NGX_OK) { | |
404 return rc; | |
405 } | |
406 | 350 |
407 ctx->ssi = ssi_ctx; | 351 ctx->ssi = ssi_ctx; |
408 | 352 |
409 handler = params[NGX_HTTP_PERL_SSI_SUB]; | 353 handler = params[NGX_HTTP_PERL_SSI_SUB]; |
410 handler->data[handler->len] = '\0'; | 354 handler->data[handler->len] = '\0'; |
411 | 355 |
412 { | 356 { |
413 | 357 |
414 dTHXa(ctx->perl); | 358 dTHXa(pmcf->perl); |
415 | 359 |
416 #if 0 | 360 #if 0 |
417 | 361 |
418 /* the code is disabled to force the precompiled perl code using only */ | 362 /* the code is disabled to force the precompiled perl code using only */ |
419 | 363 |
438 | 382 |
439 SvREFCNT_dec(sv); | 383 SvREFCNT_dec(sv); |
440 | 384 |
441 } | 385 } |
442 | 386 |
443 ngx_http_perl_free_interpreter(pmcf, ctx->perl); | |
444 | |
445 ctx->filename.data = NULL; | 387 ctx->filename.data = NULL; |
446 ctx->redirect_uri.len = 0; | 388 ctx->redirect_uri.len = 0; |
447 ctx->ssi = NULL; | 389 ctx->ssi = NULL; |
448 | 390 |
449 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi done"); | 391 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi done"); |
452 } | 394 } |
453 | 395 |
454 #endif | 396 #endif |
455 | 397 |
456 | 398 |
457 static ngx_int_t | |
458 ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf, | |
459 PerlInterpreter **perl, ngx_log_t *log) | |
460 { | |
461 if (pmcf->interp) { | |
462 pmcf->interp--; | |
463 | |
464 *perl = pmcf->free_perls[pmcf->interp]; | |
465 | |
466 return NGX_OK; | |
467 } | |
468 | |
469 if (pmcf->nalloc < pmcf->interp_max) { | |
470 *perl = ngx_http_perl_create_interpreter(pmcf, log); | |
471 | |
472 if (*perl) { | |
473 return NGX_OK; | |
474 } | |
475 | |
476 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
477 } | |
478 | |
479 ngx_log_error(NGX_LOG_ALERT, log, 0, "no free perl interpreter"); | |
480 | |
481 return NGX_HTTP_SERVICE_UNAVAILABLE; | |
482 } | |
483 | |
484 | |
485 static ngx_inline void | |
486 ngx_http_perl_free_interpreter(ngx_http_perl_main_conf_t *pmcf, | |
487 PerlInterpreter *perl) | |
488 { | |
489 pmcf->free_perls[pmcf->interp++] = perl; | |
490 } | |
491 | |
492 | |
493 static char * | 399 static char * |
494 ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf) | 400 ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf) |
495 { | 401 { |
496 #if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY) | 402 #if (NGX_HAVE_PERL_MULTIPLICITY) |
497 ngx_pool_cleanup_t *cln; | 403 ngx_pool_cleanup_t *cln; |
498 | 404 |
499 cln = ngx_pool_cleanup_add(cf->pool, 0); | 405 cln = ngx_pool_cleanup_add(cf->pool, 0); |
500 if (cln == NULL) { | 406 if (cln == NULL) { |
501 return NGX_CONF_ERROR; | 407 return NGX_CONF_ERROR; |
515 if (ngx_conf_full_name(cf->cycle, &pmcf->modules) != NGX_OK) { | 421 if (ngx_conf_full_name(cf->cycle, &pmcf->modules) != NGX_OK) { |
516 return NGX_CONF_ERROR; | 422 return NGX_CONF_ERROR; |
517 } | 423 } |
518 } | 424 } |
519 | 425 |
520 #if !(NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY) | 426 #if !(NGX_HAVE_PERL_MULTIPLICITY) |
521 | 427 |
522 if (perl) { | 428 if (perl) { |
523 if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) | 429 if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) |
524 != NGX_OK) | 430 != NGX_OK) |
525 { | 431 { |
540 if (pmcf->perl == NULL) { | 446 if (pmcf->perl == NULL) { |
541 PERL_SYS_TERM(); | 447 PERL_SYS_TERM(); |
542 return NGX_CONF_ERROR; | 448 return NGX_CONF_ERROR; |
543 } | 449 } |
544 | 450 |
545 #if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY) | 451 #if (NGX_HAVE_PERL_MULTIPLICITY) |
546 | 452 |
547 cln->handler = ngx_http_perl_cleanup_perl; | 453 cln->handler = ngx_http_perl_cleanup_perl; |
548 cln->data = pmcf->perl; | 454 cln->data = pmcf->perl; |
549 | 455 |
550 #else | 456 #else |
567 char *ver, *embedding[6]; | 473 char *ver, *embedding[6]; |
568 PerlInterpreter *perl; | 474 PerlInterpreter *perl; |
569 | 475 |
570 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter"); | 476 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter"); |
571 | 477 |
572 #if (NGX_HAVE_PERL_CLONE) | |
573 | |
574 if (pmcf->perl) { | |
575 | |
576 perl = perl_clone(pmcf->perl, CLONEf_KEEP_PTR_TABLE); | |
577 if (perl == NULL) { | |
578 ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_clone() failed"); | |
579 return NULL; | |
580 } | |
581 | |
582 { | |
583 | |
584 dTHXa(perl); | |
585 | |
586 ptr_table_free(PL_ptr_table); | |
587 PL_ptr_table = NULL; | |
588 | |
589 } | |
590 | |
591 pmcf->nalloc++; | |
592 | |
593 return perl; | |
594 } | |
595 | |
596 #endif | |
597 | |
598 perl = perl_alloc(); | 478 perl = perl_alloc(); |
599 if (perl == NULL) { | 479 if (perl == NULL) { |
600 ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_alloc() failed"); | 480 ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_alloc() failed"); |
601 return NULL; | 481 return NULL; |
602 } | 482 } |
646 if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, log) != NGX_OK) { | 526 if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, log) != NGX_OK) { |
647 goto fail; | 527 goto fail; |
648 } | 528 } |
649 | 529 |
650 } | 530 } |
651 | |
652 pmcf->nalloc++; | |
653 | 531 |
654 return perl; | 532 return perl; |
655 | 533 |
656 fail: | 534 fail: |
657 | 535 |
822 pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t)); | 700 pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t)); |
823 if (pmcf == NULL) { | 701 if (pmcf == NULL) { |
824 return NGX_CONF_ERROR; | 702 return NGX_CONF_ERROR; |
825 } | 703 } |
826 | 704 |
827 pmcf->interp_max = NGX_CONF_UNSET_UINT; | |
828 | |
829 if (ngx_array_init(&pmcf->requires, cf->pool, 1, sizeof(u_char *)) | 705 if (ngx_array_init(&pmcf->requires, cf->pool, 1, sizeof(u_char *)) |
830 != NGX_OK) | 706 != NGX_OK) |
831 { | 707 { |
832 return NULL; | 708 return NULL; |
833 } | 709 } |
839 static char * | 715 static char * |
840 ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf) | 716 ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf) |
841 { | 717 { |
842 ngx_http_perl_main_conf_t *pmcf = conf; | 718 ngx_http_perl_main_conf_t *pmcf = conf; |
843 | 719 |
844 #if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY) | |
845 ngx_conf_init_uint_value(pmcf->interp_max, 10); | |
846 #else | |
847 ngx_conf_init_uint_value(pmcf->interp_max, 1); | |
848 #endif | |
849 | |
850 pmcf->free_perls = ngx_pcalloc(cf->pool, | |
851 pmcf->interp_max * sizeof(PerlInterpreter *)); | |
852 if (pmcf->free_perls == NULL) { | |
853 return NGX_CONF_ERROR; | |
854 } | |
855 | |
856 if (pmcf->perl == NULL) { | 720 if (pmcf->perl == NULL) { |
857 if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) { | 721 if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) { |
858 return NGX_CONF_ERROR; | 722 return NGX_CONF_ERROR; |
859 } | 723 } |
860 } | 724 } |
861 | 725 |
862 #if !(NGX_HAVE_PERL_CLONE) | |
863 ngx_http_perl_free_interpreter(pmcf, pmcf->perl); | |
864 #endif | |
865 | |
866 return NGX_CONF_OK; | 726 return NGX_CONF_OK; |
867 } | 727 } |
868 | 728 |
869 | 729 |
870 #if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY) | 730 #if (NGX_HAVE_PERL_MULTIPLICITY) |
871 | 731 |
872 static void | 732 static void |
873 ngx_http_perl_cleanup_perl(void *data) | 733 ngx_http_perl_cleanup_perl(void *data) |
874 { | 734 { |
875 PerlInterpreter *perl = data; | 735 PerlInterpreter *perl = data; |
1121 v->get_handler = ngx_http_perl_variable; | 981 v->get_handler = ngx_http_perl_variable; |
1122 v->data = (uintptr_t) pv; | 982 v->data = (uintptr_t) pv; |
1123 | 983 |
1124 return NGX_CONF_OK; | 984 return NGX_CONF_OK; |
1125 } | 985 } |
1126 | |
1127 | |
1128 static char * | |
1129 ngx_http_perl_interp_max_unsupported(ngx_conf_t *cf, void *post, void *data) | |
1130 { | |
1131 #if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY) | |
1132 | |
1133 return NGX_CONF_OK; | |
1134 | |
1135 #else | |
1136 | |
1137 return "to use perl_interp_max you have to build perl with " | |
1138 "-Dusemultiplicity or -Dusethreads options"; | |
1139 | |
1140 #endif | |
1141 } |