Mercurial > hg > nginx
comparison src/http/modules/perl/ngx_http_perl_module.c @ 3239:8254055b6693 stable-0.7
merge r2972, r2994, r3133, r3142, r3143, r3174, r3175, r3176:
various perl fixes:
*) fix ngx_http_send_special() for subrequests handled by perl
*) allow perl "sub{..."
*) restore environ, this fixes segfault on reconfiguration failure when
perl module creates new environment
*) optimize error handling
*) use ngx_conf_set_str_array_slot() for perl_require
*) allow several perl_modules
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 26 Oct 2009 16:22:24 +0000 |
parents | 2efa8d2fcde1 |
children | f419516d8e6e |
comparison
equal
deleted
inserted
replaced
3238:415400fa0f10 | 3239:8254055b6693 |
---|---|
11 | 11 |
12 | 12 |
13 typedef struct { | 13 typedef struct { |
14 PerlInterpreter *perl; | 14 PerlInterpreter *perl; |
15 HV *nginx; | 15 HV *nginx; |
16 ngx_str_t modules; | 16 ngx_array_t *modules; |
17 ngx_array_t requires; | 17 ngx_array_t *requires; |
18 } ngx_http_perl_main_conf_t; | 18 } ngx_http_perl_main_conf_t; |
19 | 19 |
20 | 20 |
21 typedef struct { | 21 typedef struct { |
22 SV *sub; | 22 SV *sub; |
55 static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf); | 55 static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf); |
56 static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf); | 56 static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf); |
57 static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf); | 57 static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf); |
58 static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, | 58 static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, |
59 void *child); | 59 void *child); |
60 static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, | |
61 void *conf); | |
62 static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 60 static char *ngx_http_perl(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); | 61 static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
64 | 62 |
65 #if (NGX_HAVE_PERL_MULTIPLICITY) | 63 #if (NGX_HAVE_PERL_MULTIPLICITY) |
66 static void ngx_http_perl_cleanup_perl(void *data); | 64 static void ngx_http_perl_cleanup_perl(void *data); |
72 | 70 |
73 static ngx_command_t ngx_http_perl_commands[] = { | 71 static ngx_command_t ngx_http_perl_commands[] = { |
74 | 72 |
75 { ngx_string("perl_modules"), | 73 { ngx_string("perl_modules"), |
76 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | 74 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, |
77 ngx_conf_set_str_slot, | 75 ngx_conf_set_str_array_slot, |
78 NGX_HTTP_MAIN_CONF_OFFSET, | 76 NGX_HTTP_MAIN_CONF_OFFSET, |
79 offsetof(ngx_http_perl_main_conf_t, modules), | 77 offsetof(ngx_http_perl_main_conf_t, modules), |
80 NULL }, | 78 NULL }, |
81 | 79 |
82 { ngx_string("perl_require"), | 80 { ngx_string("perl_require"), |
83 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | 81 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, |
84 ngx_http_perl_require, | 82 ngx_conf_set_str_array_slot, |
85 NGX_HTTP_MAIN_CONF_OFFSET, | 83 NGX_HTTP_MAIN_CONF_OFFSET, |
86 0, | 84 offsetof(ngx_http_perl_main_conf_t, requires), |
87 NULL }, | 85 NULL }, |
88 | 86 |
89 { ngx_string("perl"), | 87 { ngx_string("perl"), |
90 NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1, | 88 NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1, |
91 ngx_http_perl, | 89 ngx_http_perl, |
456 | 454 |
457 | 455 |
458 static char * | 456 static char * |
459 ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf) | 457 ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf) |
460 { | 458 { |
459 ngx_str_t *m; | |
460 ngx_uint_t i; | |
461 #if (NGX_HAVE_PERL_MULTIPLICITY) | 461 #if (NGX_HAVE_PERL_MULTIPLICITY) |
462 ngx_pool_cleanup_t *cln; | 462 ngx_pool_cleanup_t *cln; |
463 | 463 |
464 cln = ngx_pool_cleanup_add(cf->pool, 0); | 464 cln = ngx_pool_cleanup_add(cf->pool, 0); |
465 if (cln == NULL) { | 465 if (cln == NULL) { |
466 return NGX_CONF_ERROR; | 466 return NGX_CONF_ERROR; |
467 } | 467 } |
469 #else | 469 #else |
470 static PerlInterpreter *perl; | 470 static PerlInterpreter *perl; |
471 #endif | 471 #endif |
472 | 472 |
473 #ifdef NGX_PERL_MODULES | 473 #ifdef NGX_PERL_MODULES |
474 if (pmcf->modules.data == NULL) { | 474 if (pmcf->modules == NGX_CONF_UNSET_PTR) { |
475 pmcf->modules.data = NGX_PERL_MODULES; | 475 |
476 } | 476 pmcf->modules = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t)); |
477 #endif | 477 if (pmcf->modules == NULL) { |
478 | |
479 if (pmcf->modules.data) { | |
480 if (ngx_conf_full_name(cf->cycle, &pmcf->modules, 0) != NGX_OK) { | |
481 return NGX_CONF_ERROR; | 478 return NGX_CONF_ERROR; |
479 } | |
480 | |
481 m = ngx_array_push(pmcf->modules); | |
482 if (m == NULL) { | |
483 return NGX_CONF_ERROR; | |
484 } | |
485 | |
486 m->len = sizeof(NGX_PERL_MODULES) - 1; | |
487 m->data = NGX_PERL_MODULES; | |
488 } | |
489 #endif | |
490 | |
491 if (pmcf->modules != NGX_CONF_UNSET_PTR) { | |
492 m = pmcf->modules->elts; | |
493 for (i = 0; i < pmcf->modules->nelts; i++) { | |
494 if (ngx_conf_full_name(cf->cycle, &m[i], 0) != NGX_OK) { | |
495 return NGX_CONF_ERROR; | |
496 } | |
482 } | 497 } |
483 } | 498 } |
484 | 499 |
485 #if !(NGX_HAVE_PERL_MULTIPLICITY) | 500 #if !(NGX_HAVE_PERL_MULTIPLICITY) |
486 | 501 |
488 | 503 |
489 if (ngx_set_environment(cf->cycle, NULL) == NULL) { | 504 if (ngx_set_environment(cf->cycle, NULL) == NULL) { |
490 return NGX_CONF_ERROR; | 505 return NGX_CONF_ERROR; |
491 } | 506 } |
492 | 507 |
493 if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) | 508 if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log) |
494 != NGX_OK) | 509 != NGX_OK) |
495 { | 510 { |
496 return NGX_CONF_ERROR; | 511 return NGX_CONF_ERROR; |
497 } | 512 } |
498 | 513 |
536 ngx_http_perl_main_conf_t *pmcf) | 551 ngx_http_perl_main_conf_t *pmcf) |
537 { | 552 { |
538 int n; | 553 int n; |
539 STRLEN len; | 554 STRLEN len; |
540 SV *sv; | 555 SV *sv; |
541 char *ver, *embedding[6]; | 556 char *ver, **embedding; |
557 ngx_str_t *m; | |
558 ngx_uint_t i; | |
542 PerlInterpreter *perl; | 559 PerlInterpreter *perl; |
543 | 560 |
544 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter"); | 561 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter"); |
545 | 562 |
546 if (ngx_set_environment(cf->cycle, NULL) == NULL) { | 563 if (ngx_set_environment(cf->cycle, NULL) == NULL) { |
562 | 579 |
563 #ifdef PERL_EXIT_DESTRUCT_END | 580 #ifdef PERL_EXIT_DESTRUCT_END |
564 PL_exit_flags |= PERL_EXIT_DESTRUCT_END; | 581 PL_exit_flags |= PERL_EXIT_DESTRUCT_END; |
565 #endif | 582 #endif |
566 | 583 |
584 n = (pmcf->modules != NGX_CONF_UNSET_PTR) ? pmcf->modules->nelts * 2 : 0; | |
585 | |
586 embedding = ngx_palloc(cf->pool, (4 + n) * sizeof(char *)); | |
587 if (embedding == NULL) { | |
588 goto fail; | |
589 } | |
590 | |
567 embedding[0] = ""; | 591 embedding[0] = ""; |
568 | 592 |
569 if (pmcf->modules.data) { | 593 if (n++) { |
570 embedding[1] = "-I"; | 594 m = pmcf->modules->elts; |
571 embedding[2] = (char *) pmcf->modules.data; | 595 for (i = 0; i < pmcf->modules->nelts; i++) { |
572 n = 3; | 596 embedding[2 * i + 1] = "-I"; |
573 | 597 embedding[2 * i + 2] = (char *) m[i].data; |
574 } else { | 598 } |
575 n = 1; | |
576 } | 599 } |
577 | 600 |
578 embedding[n++] = "-Mnginx"; | 601 embedding[n++] = "-Mnginx"; |
579 embedding[n++] = "-e"; | 602 embedding[n++] = "-e"; |
580 embedding[n++] = "0"; | 603 embedding[n++] = "0"; |
594 "version " NGINX_VERSION " of nginx.pm is required, " | 617 "version " NGINX_VERSION " of nginx.pm is required, " |
595 "but %s was found", ver); | 618 "but %s was found", ver); |
596 goto fail; | 619 goto fail; |
597 } | 620 } |
598 | 621 |
599 if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) != NGX_OK) { | 622 if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log) != NGX_OK) { |
600 goto fail; | 623 goto fail; |
601 } | 624 } |
602 | 625 |
603 } | 626 } |
604 | 627 |
615 | 638 |
616 | 639 |
617 static ngx_int_t | 640 static ngx_int_t |
618 ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log) | 641 ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log) |
619 { | 642 { |
620 char **script; | 643 u_char *err; |
621 STRLEN len; | 644 STRLEN len; |
622 ngx_str_t err; | 645 ngx_str_t *script; |
623 ngx_uint_t i; | 646 ngx_uint_t i; |
647 | |
648 if (requires == NGX_CONF_UNSET_PTR) { | |
649 return NGX_OK; | |
650 } | |
624 | 651 |
625 script = requires->elts; | 652 script = requires->elts; |
626 for (i = 0; i < requires->nelts; i++) { | 653 for (i = 0; i < requires->nelts; i++) { |
627 | 654 |
628 require_pv(script[i]); | 655 require_pv((char *) script[i].data); |
629 | 656 |
630 if (SvTRUE(ERRSV)) { | 657 if (SvTRUE(ERRSV)) { |
631 | 658 |
632 err.data = (u_char *) SvPV(ERRSV, len); | 659 err = (u_char *) SvPV(ERRSV, len); |
633 for (len--; err.data[len] == LF || err.data[len] == CR; len--) { | 660 while (--len && (err[len] == CR || err[len] == LF)) { /* void */ } |
634 /* void */ | |
635 } | |
636 err.len = len + 1; | |
637 | 661 |
638 ngx_log_error(NGX_LOG_EMERG, log, 0, | 662 ngx_log_error(NGX_LOG_EMERG, log, 0, |
639 "require_pv(\"%s\") failed: \"%V\"", script[i], &err); | 663 "require_pv(\"%s\") failed: \"%*s\"", |
664 script[i].data, len + 1, err); | |
640 | 665 |
641 return NGX_ERROR; | 666 return NGX_ERROR; |
642 } | 667 } |
643 } | 668 } |
644 | 669 |
651 SV **args, ngx_str_t *handler, ngx_str_t *rv) | 676 SV **args, ngx_str_t *handler, ngx_str_t *rv) |
652 { | 677 { |
653 SV *sv; | 678 SV *sv; |
654 int n, status; | 679 int n, status; |
655 char *line; | 680 char *line; |
681 u_char *err; | |
656 STRLEN len, n_a; | 682 STRLEN len, n_a; |
657 ngx_str_t err; | |
658 ngx_uint_t i; | 683 ngx_uint_t i; |
659 ngx_connection_t *c; | 684 ngx_connection_t *c; |
660 | 685 |
661 dSP; | 686 dSP; |
662 | 687 |
722 | 747 |
723 /* check $@ */ | 748 /* check $@ */ |
724 | 749 |
725 if (SvTRUE(ERRSV)) { | 750 if (SvTRUE(ERRSV)) { |
726 | 751 |
727 err.data = (u_char *) SvPV(ERRSV, len); | 752 err = (u_char *) SvPV(ERRSV, len); |
728 for (len--; err.data[len] == LF || err.data[len] == CR; len--) { | 753 while (--len && (err[len] == CR || err[len] == LF)) { /* void */ } |
729 /* void */ | |
730 } | |
731 err.len = len + 1; | |
732 | 754 |
733 ngx_log_error(NGX_LOG_ERR, c->log, 0, | 755 ngx_log_error(NGX_LOG_ERR, c->log, 0, |
734 "call_sv(\"%V\") failed: \"%V\"", handler, &err); | 756 "call_sv(\"%V\") failed: \"%*s\"", handler, len + 1, err); |
735 | 757 |
736 if (rv) { | 758 if (rv) { |
737 return NGX_ERROR; | 759 return NGX_ERROR; |
738 } | 760 } |
739 | 761 |
763 if (*p != ' ' && *p != '\t' && *p != CR && *p != LF) { | 785 if (*p != ' ' && *p != '\t' && *p != CR && *p != LF) { |
764 break; | 786 break; |
765 } | 787 } |
766 } | 788 } |
767 | 789 |
768 if (ngx_strncmp(p, "sub ", 4) == 0 || ngx_strncmp(p, "use ", 4) == 0) { | 790 if (ngx_strncmp(p, "sub ", 4) == 0 |
791 || ngx_strncmp(p, "sub{", 4) == 0 | |
792 || ngx_strncmp(p, "use ", 4) == 0) | |
793 { | |
769 *sv = eval_pv((char *) p, FALSE); | 794 *sv = eval_pv((char *) p, FALSE); |
770 | 795 |
771 /* eval_pv() does not set ERRSV on failure */ | 796 /* eval_pv() does not set ERRSV on failure */ |
772 | 797 |
773 return; | 798 return; |
785 pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t)); | 810 pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t)); |
786 if (pmcf == NULL) { | 811 if (pmcf == NULL) { |
787 return NULL; | 812 return NULL; |
788 } | 813 } |
789 | 814 |
790 if (ngx_array_init(&pmcf->requires, cf->pool, 1, sizeof(u_char *)) | 815 pmcf->modules = NGX_CONF_UNSET_PTR; |
791 != NGX_OK) | 816 pmcf->requires = NGX_CONF_UNSET_PTR; |
792 { | |
793 return NULL; | |
794 } | |
795 | 817 |
796 return pmcf; | 818 return pmcf; |
797 } | 819 } |
798 | 820 |
799 | 821 |
896 return NGX_CONF_OK; | 918 return NGX_CONF_OK; |
897 } | 919 } |
898 | 920 |
899 | 921 |
900 static char * | 922 static char * |
901 ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
902 { | |
903 ngx_http_perl_main_conf_t *pmcf = conf; | |
904 | |
905 u_char **p; | |
906 ngx_str_t *value; | |
907 | |
908 value = cf->args->elts; | |
909 | |
910 p = ngx_array_push(&pmcf->requires); | |
911 | |
912 if (p == NULL) { | |
913 return NGX_CONF_ERROR; | |
914 } | |
915 | |
916 *p = value[1].data; | |
917 | |
918 return NGX_CONF_OK; | |
919 } | |
920 | |
921 | |
922 static char * | |
923 ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 923 ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
924 { | 924 { |
925 ngx_http_perl_loc_conf_t *plcf = conf; | 925 ngx_http_perl_loc_conf_t *plcf = conf; |
926 | 926 |
927 ngx_str_t *value; | 927 ngx_str_t *value; |