1# vim:set ft= ts=4 sw=4 et fdm=marker: 2 3use Test::Nginx::Socket::Lua; 4use t::StapThread; 5 6our $GCScript = $t::StapThread::GCScript; 7our $StapScript = $t::StapThread::StapScript; 8 9repeat_each(2); 10 11plan tests => repeat_each() * (blocks() * 4); 12 13$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8'; 14$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211'; 15$ENV{TEST_NGINX_REDIS_PORT} ||= '6379'; 16 17#no_shuffle(); 18no_long_string(); 19run_tests(); 20 21__DATA__ 22 23=== TEST 1: exit in user thread (entry thread is still pending to run) 24--- config 25 location /lua { 26 access_by_lua ' 27 local function f() 28 ngx.say("hello in thread") 29 ngx.exit(0) 30 end 31 32 ngx.say("before") 33 ngx.thread.spawn(f) 34 ngx.say("after") 35 ngx.sleep(1) 36 ngx.say("end") 37 '; 38 } 39--- request 40GET /lua 41--- stap2 eval: $::StapScript 42--- stap eval 43<<'_EOC_' . $::GCScript; 44 45global timers 46 47M(timer-add) { 48 if ($arg2 == 1000) { 49 timers[$arg1] = $arg2 50 printf("add timer %d\n", $arg2) 51 } 52} 53 54M(timer-del) { 55 tm = timers[$arg1] 56 if (tm == 1000) { 57 printf("delete timer %d\n", tm) 58 delete timers[$arg1] 59 } 60} 61 62M(timer-expire) { 63 tm = timers[$arg1] 64 if (tm == 1000) { 65 printf("expire timer %d\n", timers[$arg1]) 66 delete timers[$arg1] 67 } 68} 69_EOC_ 70 71--- stap_out 72create 2 in 1 73spawn user thread 2 in 1 74terminate 2: ok 75delete thread 2 76delete thread 1 77 78--- response_body 79before 80hello in thread 81--- no_error_log 82[error] 83 84 85 86=== TEST 2: exit in user thread (entry thread is still pending on ngx.sleep) 87--- config 88 location /lua { 89 access_by_lua ' 90 local function f() 91 ngx.say("hello in thread") 92 ngx.sleep(0.1) 93 ngx.exit(0) 94 end 95 96 ngx.say("before") 97 ngx.thread.spawn(f) 98 ngx.say("after") 99 ngx.sleep(1) 100 ngx.say("end") 101 '; 102 } 103--- request 104GET /lua 105--- stap2 eval: $::StapScript 106--- stap eval 107<<'_EOC_' . $::GCScript; 108 109global timers 110 111F(ngx_http_free_request) { 112 println("free request") 113} 114 115M(timer-add) { 116 if ($arg2 == 1000 || $arg2 == 100) { 117 timers[$arg1] = $arg2 118 printf("add timer %d\n", $arg2) 119 } 120} 121 122M(timer-del) { 123 tm = timers[$arg1] 124 if (tm == 1000 || tm == 100) { 125 printf("delete timer %d\n", tm) 126 delete timers[$arg1] 127 } 128 /* 129 if (tm == 1000) { 130 print_ubacktrace() 131 } 132 */ 133} 134 135M(timer-expire) { 136 tm = timers[$arg1] 137 if (tm == 1000 || tm == 100) { 138 printf("expire timer %d\n", timers[$arg1]) 139 delete timers[$arg1] 140 } 141} 142 143F(ngx_http_lua_sleep_cleanup) { 144 println("lua sleep cleanup") 145} 146_EOC_ 147 148--- stap_out 149create 2 in 1 150spawn user thread 2 in 1 151add timer 100 152add timer 1000 153expire timer 100 154terminate 2: ok 155delete thread 2 156lua sleep cleanup 157delete timer 1000 158delete thread 1 159free request 160 161--- wait: 0.1 162--- response_body 163before 164hello in thread 165after 166--- no_error_log 167[error] 168 169 170 171=== TEST 3: exit in a user thread (another user thread is still pending on ngx.sleep) 172--- config 173 location /lua { 174 access_by_lua ' 175 local function f() 176 ngx.sleep(0.1) 177 ngx.say("f") 178 ngx.exit(0) 179 end 180 181 local function g() 182 ngx.sleep(1) 183 ngx.say("g") 184 end 185 186 ngx.thread.spawn(f) 187 ngx.thread.spawn(g) 188 ngx.say("end") 189 '; 190 } 191--- request 192GET /lua 193--- stap2 eval: $::StapScript 194--- stap eval 195<<'_EOC_' . $::GCScript; 196 197global timers 198 199F(ngx_http_free_request) { 200 println("free request") 201} 202 203M(timer-add) { 204 if ($arg2 == 1000 || $arg2 == 100) { 205 timers[$arg1] = $arg2 206 printf("add timer %d\n", $arg2) 207 } 208} 209 210M(timer-del) { 211 tm = timers[$arg1] 212 if (tm == 1000 || tm == 100) { 213 printf("delete timer %d\n", tm) 214 delete timers[$arg1] 215 } 216 /* 217 if (tm == 1000) { 218 print_ubacktrace() 219 } 220 */ 221} 222 223M(timer-expire) { 224 tm = timers[$arg1] 225 if (tm == 1000 || tm == 100) { 226 printf("expire timer %d\n", timers[$arg1]) 227 delete timers[$arg1] 228 } 229} 230 231F(ngx_http_lua_sleep_cleanup) { 232 println("lua sleep cleanup") 233} 234_EOC_ 235 236--- stap_out 237create 2 in 1 238spawn user thread 2 in 1 239add timer 100 240create 3 in 1 241spawn user thread 3 in 1 242add timer 1000 243terminate 1: ok 244delete thread 1 245expire timer 100 246terminate 2: ok 247delete thread 2 248lua sleep cleanup 249delete timer 1000 250delete thread 3 251free request 252 253--- response_body 254end 255f 256--- no_error_log 257[error] 258 259 260 261=== TEST 4: exit in user thread (entry already quits) 262--- config 263 location /lua { 264 access_by_lua ' 265 local function f() 266 ngx.sleep(0.1) 267 ngx.say("exiting the user thread") 268 ngx.exit(0) 269 end 270 271 ngx.say("before") 272 ngx.thread.spawn(f) 273 ngx.say("after") 274 '; 275 } 276--- request 277GET /lua 278--- stap2 eval: $::StapScript 279--- stap eval: $::GCScript 280--- stap_out 281create 2 in 1 282spawn user thread 2 in 1 283terminate 1: ok 284delete thread 1 285terminate 2: ok 286delete thread 2 287 288--- wait: 0.1 289--- response_body 290before 291after 292exiting the user thread 293--- no_error_log 294[error] 295 296 297 298=== TEST 5: exit in user thread (entry thread is still pending on the DNS resolver for ngx.socket.tcp) 299--- config 300 location /lua { 301 resolver 127.0.0.2:12345; 302 resolver_timeout 12s; 303 access_by_lua ' 304 local function f() 305 ngx.say("hello in thread") 306 ngx.sleep(0.001) 307 ngx.exit(0) 308 end 309 310 ngx.say("before") 311 ngx.thread.spawn(f) 312 ngx.say("after") 313 local sock = ngx.socket.tcp() 314 local ok, err = sock:connect("agentzh.org", 80) 315 if not ok then 316 ngx.say("failed to connect: ", err) 317 return 318 end 319 ngx.say("end") 320 '; 321 } 322--- request 323GET /lua 324--- stap2 eval: $::StapScript 325--- stap eval 326<<'_EOC_' . $::GCScript; 327 328global timers 329 330F(ngx_http_free_request) { 331 println("free request") 332} 333 334F(ngx_resolve_name) { 335 printf("resolving %s\n", user_string_n($ctx->name->data, $ctx->name->len)) 336} 337 338M(timer-add) { 339 if ($arg2 == 12000 || $arg2 == 1) { 340 timers[$arg1] = $arg2 341 printf("add timer %d\n", $arg2) 342 } 343} 344 345M(timer-del) { 346 tm = timers[$arg1] 347 if (tm == 12000 || tm == 1) { 348 printf("delete timer %d\n", tm) 349 delete timers[$arg1] 350 } 351 /* 352 if (tm == 12000) { 353 print_ubacktrace() 354 } 355 */ 356} 357 358M(timer-expire) { 359 tm = timers[$arg1] 360 if (tm == 12000 || tm == 1) { 361 printf("expire timer %d\n", timers[$arg1]) 362 delete timers[$arg1] 363 } 364} 365 366F(ngx_http_lua_tcp_resolve_cleanup) { 367 println("lua tcp resolve cleanup") 368} 369_EOC_ 370 371--- stap_out 372create 2 in 1 373spawn user thread 2 in 1 374add timer 1 375resolving agentzh.org 376add timer 12000 377expire timer 1 378terminate 2: ok 379delete thread 2 380lua tcp resolve cleanup 381delete timer 12000 382delete thread 1 383free request 384 385--- response_body 386before 387hello in thread 388after 389--- no_error_log 390[error] 391 392 393 394=== TEST 6: exit in user thread (entry thread is still pending on the DNS resolver for ngx.socket.udp) 395--- config 396 location /lua { 397 resolver 127.0.0.2:12345; 398 resolver_timeout 12s; 399 access_by_lua ' 400 local function f() 401 ngx.say("hello in thread") 402 ngx.sleep(0.001) 403 ngx.exit(0) 404 end 405 406 ngx.say("before") 407 ngx.thread.spawn(f) 408 ngx.say("after") 409 local sock = ngx.socket.udp() 410 local ok, err = sock:setpeername("agentzh.org", 80) 411 if not ok then 412 ngx.say("failed to connect: ", err) 413 return 414 end 415 ngx.say("end") 416 '; 417 } 418--- request 419GET /lua 420--- stap2 eval: $::StapScript 421--- stap eval 422<<'_EOC_' . $::GCScript; 423 424global timers 425 426F(ngx_http_free_request) { 427 println("free request") 428} 429 430F(ngx_resolve_name) { 431 printf("resolving %s\n", user_string_n($ctx->name->data, $ctx->name->len)) 432} 433 434M(timer-add) { 435 if ($arg2 == 12000 || $arg2 == 1) { 436 timers[$arg1] = $arg2 437 printf("add timer %d\n", $arg2) 438 } 439} 440 441M(timer-del) { 442 tm = timers[$arg1] 443 if (tm == 12000 || tm == 1) { 444 printf("delete timer %d\n", tm) 445 delete timers[$arg1] 446 } 447 /* 448 if (tm == 12000) { 449 print_ubacktrace() 450 } 451 */ 452} 453 454M(timer-expire) { 455 tm = timers[$arg1] 456 if (tm == 12000 || tm == 1) { 457 printf("expire timer %d\n", timers[$arg1]) 458 delete timers[$arg1] 459 } 460} 461 462F(ngx_http_lua_udp_resolve_cleanup) { 463 println("lua udp resolve cleanup") 464} 465_EOC_ 466 467--- stap_out 468create 2 in 1 469spawn user thread 2 in 1 470add timer 1 471resolving agentzh.org 472add timer 12000 473expire timer 1 474terminate 2: ok 475delete thread 2 476lua udp resolve cleanup 477delete timer 12000 478delete thread 1 479free request 480 481--- response_body 482before 483hello in thread 484after 485--- no_error_log 486[error] 487 488 489 490=== TEST 7: exit in user thread (entry thread is still pending on tcpsock:connect) 491--- config 492 location /lua { 493 access_by_lua ' 494 local function f() 495 ngx.say("hello in thread") 496 ngx.sleep(0.1) 497 ngx.exit(0) 498 end 499 500 ngx.say("before") 501 ngx.thread.spawn(f) 502 ngx.say("after") 503 local sock = ngx.socket.tcp() 504 sock:settimeout(12000) 505 local ok, err = sock:connect("127.0.0.2", 12345) 506 if not ok then 507 ngx.say("failed to connect: ", err) 508 return 509 end 510 ngx.say("end") 511 '; 512 } 513--- request 514GET /lua 515--- stap2 eval: $::StapScript 516--- stap eval 517<<'_EOC_' . $::GCScript; 518 519global timers 520 521F(ngx_http_free_request) { 522 println("free request") 523} 524 525M(timer-add) { 526 if ($arg2 == 12000 || $arg2 == 100) { 527 timers[$arg1] = $arg2 528 printf("add timer %d\n", $arg2) 529 } 530} 531 532M(timer-del) { 533 tm = timers[$arg1] 534 if (tm == 12000 || tm == 100) { 535 printf("delete timer %d\n", tm) 536 delete timers[$arg1] 537 } 538 /* 539 if (tm == 12000) { 540 print_ubacktrace() 541 } 542 */ 543} 544 545M(timer-expire) { 546 tm = timers[$arg1] 547 if (tm == 12000 || tm == 100) { 548 printf("expire timer %d\n", timers[$arg1]) 549 delete timers[$arg1] 550 } 551} 552 553F(ngx_http_lua_coctx_cleanup) { 554 println("lua tcp socket cleanup") 555} 556_EOC_ 557 558--- stap_out 559create 2 in 1 560spawn user thread 2 in 1 561add timer 100 562add timer 12000 563expire timer 100 564terminate 2: ok 565delete thread 2 566lua tcp socket cleanup 567delete timer 12000 568delete thread 1 569free request 570 571--- wait: 0.1 572--- response_body 573before 574hello in thread 575after 576--- no_error_log 577[error] 578 579 580 581=== TEST 8: exit in user thread (entry thread is still pending on tcpsock:receive) 582--- config 583 location /lua { 584 access_by_lua ' 585 local function f() 586 ngx.say("hello in thread") 587 ngx.sleep(0.1) 588 ngx.exit(0) 589 end 590 591 ngx.say("before") 592 ngx.thread.spawn(f) 593 ngx.say("after") 594 local sock = ngx.socket.tcp() 595 596 local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_REDIS_PORT) 597 if not ok then 598 ngx.say("failed to connect: ", err) 599 return 600 end 601 602 local bytes, ok = sock:send("blpop not_exists 2\\r\\n") 603 if not bytes then 604 ngx.say("failed to send: ", err) 605 return 606 end 607 608 sock:settimeout(12000) 609 610 local data, err = sock:receive() 611 if not data then 612 ngx.say("failed to receive: ", err) 613 return 614 end 615 616 ngx.say("end") 617 '; 618 } 619--- request 620GET /lua 621--- stap2 eval: $::StapScript 622--- stap eval 623<<'_EOC_' . $::GCScript; 624 625global timers 626 627F(ngx_http_free_request) { 628 println("free request") 629} 630 631M(timer-add) { 632 if ($arg2 == 12000 || $arg2 == 100) { 633 timers[$arg1] = $arg2 634 printf("add timer %d\n", $arg2) 635 } 636} 637 638M(timer-del) { 639 tm = timers[$arg1] 640 if (tm == 12000 || tm == 100) { 641 printf("delete timer %d\n", tm) 642 delete timers[$arg1] 643 } 644} 645 646M(timer-expire) { 647 tm = timers[$arg1] 648 if (tm == 12000 || tm == 100) { 649 printf("expire timer %d\n", timers[$arg1]) 650 delete timers[$arg1] 651 } 652} 653 654F(ngx_http_lua_coctx_cleanup) { 655 println("lua tcp socket cleanup") 656} 657_EOC_ 658 659--- stap_out 660create 2 in 1 661spawn user thread 2 in 1 662add timer 100 663add timer 12000 664expire timer 100 665terminate 2: ok 666delete thread 2 667lua tcp socket cleanup 668delete timer 12000 669delete thread 1 670free request 671 672--- response_body 673before 674hello in thread 675after 676--- no_error_log 677[error] 678 679 680 681=== TEST 9: exit in user thread (entry thread is still pending on tcpsock:receiveuntil's iterator) 682--- config 683 location /lua { 684 access_by_lua ' 685 local function f() 686 ngx.say("hello in thread") 687 ngx.sleep(0.1) 688 ngx.exit(0) 689 end 690 691 ngx.say("before") 692 ngx.thread.spawn(f) 693 ngx.say("after") 694 local sock = ngx.socket.tcp() 695 696 local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_REDIS_PORT) 697 if not ok then 698 ngx.say("failed to connect: ", err) 699 return 700 end 701 702 local bytes, ok = sock:send("blpop not_exists 2\\r\\n") 703 if not bytes then 704 ngx.say("failed to send: ", err) 705 return 706 end 707 708 local it, err = sock:receiveuntil("\\r\\n") 709 if not it then 710 ngx.say("failed to receive until: ", err) 711 return 712 end 713 714 sock:settimeout(12000) 715 716 local data, err = it() 717 if not data then 718 ngx.say("failed to receive: ", err) 719 return 720 end 721 722 ngx.say("end") 723 '; 724 } 725--- request 726GET /lua 727--- stap2 eval: $::StapScript 728--- stap eval 729<<'_EOC_' . $::GCScript; 730 731global timers 732 733F(ngx_http_free_request) { 734 println("free request") 735} 736 737M(timer-add) { 738 if ($arg2 == 12000 || $arg2 == 100) { 739 timers[$arg1] = $arg2 740 printf("add timer %d\n", $arg2) 741 } 742} 743 744M(timer-del) { 745 tm = timers[$arg1] 746 if (tm == 12000 || tm == 100) { 747 printf("delete timer %d\n", tm) 748 delete timers[$arg1] 749 } 750} 751 752M(timer-expire) { 753 tm = timers[$arg1] 754 if (tm == 12000 || tm == 100) { 755 printf("expire timer %d\n", timers[$arg1]) 756 delete timers[$arg1] 757 } 758} 759 760F(ngx_http_lua_coctx_cleanup) { 761 println("lua tcp socket cleanup") 762} 763_EOC_ 764 765--- stap_out 766create 2 in 1 767spawn user thread 2 in 1 768add timer 100 769add timer 12000 770expire timer 100 771terminate 2: ok 772delete thread 2 773lua tcp socket cleanup 774delete timer 12000 775delete thread 1 776free request 777 778--- response_body 779before 780hello in thread 781after 782--- no_error_log 783[error] 784 785 786 787=== TEST 10: exit in user thread (entry thread is still pending on udpsock:receive) 788--- config 789 location /lua { 790 access_by_lua ' 791 local function f() 792 ngx.say("hello in thread") 793 ngx.sleep(0.1) 794 ngx.exit(0) 795 end 796 797 ngx.say("before") 798 ngx.thread.spawn(f) 799 ngx.say("after") 800 local sock = ngx.socket.udp() 801 802 local ok, err = sock:setpeername("8.8.8.8", 12345) 803 if not ok then 804 ngx.say("failed to connect: ", err) 805 return 806 end 807 808 sock:settimeout(12000) 809 810 local data, err = sock:receive() 811 if not data then 812 ngx.say("failed to receive: ", err) 813 return 814 end 815 816 ngx.say("end") 817 '; 818 } 819--- request 820GET /lua 821--- stap2 eval: $::StapScript 822--- stap eval 823<<'_EOC_' . $::GCScript; 824 825global timers 826 827F(ngx_http_free_request) { 828 println("free request") 829} 830 831M(timer-add) { 832 if ($arg2 == 12000 || $arg2 == 100) { 833 timers[$arg1] = $arg2 834 printf("add timer %d\n", $arg2) 835 } 836} 837 838M(timer-del) { 839 tm = timers[$arg1] 840 if (tm == 12000 || tm == 100) { 841 printf("delete timer %d\n", tm) 842 delete timers[$arg1] 843 } 844} 845 846M(timer-expire) { 847 tm = timers[$arg1] 848 if (tm == 12000 || tm == 100) { 849 printf("expire timer %d\n", timers[$arg1]) 850 delete timers[$arg1] 851 } 852} 853 854F(ngx_http_lua_udp_socket_cleanup) { 855 println("lua udp socket cleanup") 856} 857_EOC_ 858 859--- stap_out 860create 2 in 1 861spawn user thread 2 in 1 862add timer 100 863add timer 12000 864expire timer 100 865terminate 2: ok 866delete thread 2 867lua udp socket cleanup 868delete timer 12000 869delete thread 1 870free request 871 872--- wait: 0.1 873--- response_body 874before 875hello in thread 876after 877--- no_error_log 878[error] 879 880 881 882=== TEST 11: exit in user thread (entry thread is still pending on reqsock:receive) 883--- config 884 location /lua { 885 access_by_lua ' 886 local function f() 887 ngx.say("hello in thread") 888 ngx.sleep(0.1) 889 ngx.exit(0) 890 end 891 892 ngx.say("before") 893 ngx.thread.spawn(f) 894 ngx.say("after") 895 local sock = ngx.req.socket() 896 897 sock:settimeout(12000) 898 899 local data, err = sock:receive(1024) 900 if not data then 901 ngx.say("failed to receive: ", err) 902 return 903 end 904 905 ngx.say("end") 906 '; 907 } 908--- request 909POST /lua 910 911--- more_headers 912Content-Length: 1024 913 914--- stap2 eval: $::StapScript 915--- stap eval 916<<'_EOC_' . $::GCScript; 917 918global timers 919 920F(ngx_http_free_request) { 921 println("free request") 922} 923 924M(timer-add) { 925 if ($arg2 == 12000 || $arg2 == 100) { 926 timers[$arg1] = $arg2 927 printf("add timer %d\n", $arg2) 928 } 929} 930 931M(timer-del) { 932 tm = timers[$arg1] 933 if (tm == 12000 || tm == 100) { 934 printf("delete timer %d\n", tm) 935 delete timers[$arg1] 936 } 937} 938 939M(timer-expire) { 940 tm = timers[$arg1] 941 if (tm == 12000 || tm == 100) { 942 printf("expire timer %d\n", timers[$arg1]) 943 delete timers[$arg1] 944 } 945} 946 947F(ngx_http_lua_coctx_cleanup) { 948 println("lua tcp socket cleanup") 949} 950_EOC_ 951 952--- stap_out 953create 2 in 1 954spawn user thread 2 in 1 955add timer 100 956add timer 12000 957expire timer 100 958terminate 2: ok 959delete thread 2 960lua tcp socket cleanup 961delete timer 12000 962delete thread 1 963free request 964 965--- wait: 0.1 966--- response_body 967before 968hello in thread 969after 970--- no_error_log 971[error] 972 973 974 975=== TEST 12: exit in user thread (entry thread is still pending on ngx.req.read_body) 976--- config 977 location /lua { 978 client_body_timeout 12000ms; 979 access_by_lua ' 980 local function f() 981 ngx.say("hello in thread") 982 ngx.sleep(0.1) 983 ngx.exit(0) 984 end 985 986 ngx.say("before") 987 ngx.thread.spawn(f) 988 ngx.say("after") 989 990 ngx.req.read_body() 991 992 ngx.say("end") 993 '; 994 } 995--- request 996POST /lua 997--- more_headers 998Content-Length: 1024 999--- stap2 eval: $::StapScript 1000--- stap eval 1001<<'_EOC_' . $::GCScript; 1002 1003global timers 1004 1005F(ngx_http_free_request) { 1006 println("free request") 1007} 1008 1009M(timer-add) { 1010 if ($arg2 == 12000 || $arg2 == 100) { 1011 timers[$arg1] = $arg2 1012 printf("add timer %d\n", $arg2) 1013 } 1014} 1015 1016M(timer-del) { 1017 tm = timers[$arg1] 1018 if (tm == 12000 || tm == 100) { 1019 printf("delete timer %d\n", tm) 1020 delete timers[$arg1] 1021 } 1022} 1023 1024M(timer-expire) { 1025 tm = timers[$arg1] 1026 if (tm == 12000 || tm == 100) { 1027 printf("expire timer %d\n", timers[$arg1]) 1028 delete timers[$arg1] 1029 } 1030} 1031 1032F(ngx_http_lua_req_body_cleanup) { 1033 println("lua req body cleanup") 1034} 1035_EOC_ 1036 1037--- stap_out 1038create 2 in 1 1039spawn user thread 2 in 1 1040add timer 100 1041add timer 12000 1042expire timer 100 1043terminate 2: ok 1044delete thread 2 1045lua req body cleanup 1046delete timer 12000 1047delete thread 1 1048free request 1049 1050--- wait: 0.1 1051--- response_body 1052before 1053hello in thread 1054after 1055--- no_error_log 1056[error] 1057 1058 1059 1060=== TEST 13: exit in user thread (entry thread is still pending on ngx.location.capture), with pending output 1061--- config 1062 location /lua { 1063 client_body_timeout 12000ms; 1064 access_by_lua ' 1065 local function f() 1066 ngx.say("hello in thread") 1067 ngx.sleep(0.1) 1068 ngx.exit(0) 1069 end 1070 1071 ngx.say("before") 1072 ngx.thread.spawn(f) 1073 ngx.say("after") 1074 1075 ngx.location.capture("/sleep") 1076 1077 ngx.say("end") 1078 '; 1079 } 1080 1081 location = /sleep { 1082 echo_sleep 0.2; 1083 } 1084--- request 1085POST /lua 1086--- stap2 eval: $::StapScript 1087--- stap eval 1088<<'_EOC_' . $::GCScript; 1089 1090global timers 1091 1092F(ngx_http_free_request) { 1093 println("free request") 1094} 1095 1096M(timer-add) { 1097 if ($arg2 == 200 || $arg2 == 100) { 1098 timers[$arg1] = $arg2 1099 printf("add timer %d\n", $arg2) 1100 } 1101} 1102 1103M(timer-del) { 1104 tm = timers[$arg1] 1105 if (tm == 200 || tm == 100) { 1106 printf("delete timer %d\n", tm) 1107 delete timers[$arg1] 1108 } 1109} 1110 1111M(timer-expire) { 1112 tm = timers[$arg1] 1113 if (tm == 200 || tm == 100) { 1114 printf("expire timer %d\n", timers[$arg1]) 1115 delete timers[$arg1] 1116 } 1117} 1118_EOC_ 1119 1120--- stap_out 1121create 2 in 1 1122spawn user thread 2 in 1 1123add timer 100 1124add timer 200 1125expire timer 100 1126terminate 2: fail 1127expire timer 200 1128terminate 1: ok 1129delete thread 2 1130delete thread 1 1131free request 1132 1133--- wait: 0.1 1134--- response_body 1135before 1136hello in thread 1137after 1138end 1139--- error_log 1140attempt to abort with pending subrequests 1141 1142 1143 1144=== TEST 14: exit in user thread (entry thread is still pending on ngx.location.capture), without pending output 1145--- config 1146 location /lua { 1147 client_body_timeout 12000ms; 1148 access_by_lua ' 1149 local function f() 1150 ngx.sleep(0.1) 1151 ngx.exit(0) 1152 end 1153 1154 ngx.thread.spawn(f) 1155 1156 ngx.location.capture("/sleep") 1157 ngx.say("end") 1158 '; 1159 } 1160 1161 location = /sleep { 1162 echo_sleep 0.2; 1163 } 1164--- request 1165POST /lua 1166--- stap2 eval: $::StapScript 1167--- stap eval 1168<<'_EOC_' . $::GCScript; 1169 1170global timers 1171 1172F(ngx_http_free_request) { 1173 println("free request") 1174} 1175 1176M(timer-add) { 1177 if ($arg2 == 200 || $arg2 == 100) { 1178 timers[$arg1] = $arg2 1179 printf("add timer %d\n", $arg2) 1180 } 1181} 1182 1183M(timer-del) { 1184 tm = timers[$arg1] 1185 if (tm == 200 || tm == 100) { 1186 printf("delete timer %d\n", tm) 1187 delete timers[$arg1] 1188 } 1189} 1190 1191M(timer-expire) { 1192 tm = timers[$arg1] 1193 if (tm == 200 || tm == 100) { 1194 printf("expire timer %d\n", timers[$arg1]) 1195 delete timers[$arg1] 1196 } 1197} 1198 1199F(ngx_http_lua_post_subrequest) { 1200 printf("post subreq %s\n", ngx_http_req_uri($r)) 1201} 1202 1203_EOC_ 1204 1205--- stap_out 1206create 2 in 1 1207spawn user thread 2 in 1 1208add timer 100 1209add timer 200 1210expire timer 100 1211terminate 2: fail 1212expire timer 200 1213post subreq /sleep 1214terminate 1: ok 1215delete thread 2 1216delete thread 1 1217free request 1218 1219--- wait: 0.1 1220--- response_body 1221end 1222--- error_log 1223attempt to abort with pending subrequests 1224 1225 1226 1227=== TEST 15: exit in user thread (entry thread is still pending on ngx.location.capture_multi), without pending output 1228--- config 1229 location /lua { 1230 client_body_timeout 12000ms; 1231 access_by_lua ' 1232 local function f() 1233 ngx.sleep(0.1) 1234 ngx.exit(0) 1235 end 1236 1237 ngx.thread.spawn(f) 1238 1239 ngx.location.capture_multi{ 1240 {"/echo"}, 1241 {"/sleep"} 1242 } 1243 ngx.say("end") 1244 '; 1245 } 1246 1247 location = /echo { 1248 echo hello; 1249 } 1250 1251 location = /sleep { 1252 echo_sleep 0.2; 1253 } 1254--- request 1255POST /lua 1256--- stap2 eval: $::StapScript 1257--- stap eval 1258<<'_EOC_' . $::GCScript; 1259 1260global timers 1261 1262F(ngx_http_free_request) { 1263 println("free request") 1264} 1265 1266M(timer-add) { 1267 if ($arg2 == 200 || $arg2 == 100) { 1268 timers[$arg1] = $arg2 1269 printf("add timer %d\n", $arg2) 1270 } 1271} 1272 1273M(timer-del) { 1274 tm = timers[$arg1] 1275 if (tm == 200 || tm == 100) { 1276 printf("delete timer %d\n", tm) 1277 delete timers[$arg1] 1278 } 1279} 1280 1281M(timer-expire) { 1282 tm = timers[$arg1] 1283 if (tm == 200 || tm == 100) { 1284 printf("expire timer %d\n", timers[$arg1]) 1285 delete timers[$arg1] 1286 } 1287} 1288 1289F(ngx_http_lua_post_subrequest) { 1290 printf("post subreq %s\n", ngx_http_req_uri($r)) 1291} 1292_EOC_ 1293 1294--- stap_out 1295create 2 in 1 1296spawn user thread 2 in 1 1297add timer 100 1298post subreq /echo 1299add timer 200 1300expire timer 100 1301terminate 2: fail 1302expire timer 200 1303post subreq /sleep 1304terminate 1: ok 1305delete thread 2 1306delete thread 1 1307free request 1308 1309--- wait: 0.1 1310--- response_body 1311end 1312--- error_log 1313attempt to abort with pending subrequests 1314