如何在不重新启动的情况下调试mod_perl2模块?

时间:2022-10-06 08:13:12

Environment: Apache/2.2.11 (Win32) mod_apreq2-20051231/2.6.2-dev mod_perl/2.0.4-dev Perl/v5.10.0

环境:Apache / 2.2.11(Win32)mod_apreq2-20051231 / 2.6.2-dev mod_perl / 2.0.4-dev Perl / v5.10.0

Situation very similar to what's described in this discussion list post, except for being on win32.

情况与此讨论列表帖子中描述的情况非常相似,除了在win32上。

I have this in httpd.conf:

我在httpd.conf中有这个:

PerlModule Apache2::Reload
PerlInitHandler Apache2::Reload
PerlSetVar ReloadAll Off
PerlSetVar ReloadModules "MyPackage::*"

...as well as only mod-perl script handling.

...以及只有mod-perl脚本处理。

I have a script that uses a MyPackage module, and it's working.

我有一个使用MyPackage模块的脚本,它正在运行。

I break the module, and reload the script. The error is a helpful one, telling the line where I broke the module.

我打破了模块,然后重新加载脚本。错误是一个有用的错误,告诉我打破模块的位置。

(If I reload again at this point, and it only tells me "Undefined subroutine &ModPerl::ROOT::ModPerl::Registry..." because it wasn't able to load the file the first time. But either way the following behaviour still happens.)

(如果我此时再次重新加载,它只告诉我“Undefined subroutine&ModPerl :: ROOT :: ModPerl :: Registry ...”,因为它无法在第一次加载文件。但无论如何以下行为仍然发生。)

I revert the break, and touch the script file too so it'll reload the module, and reload. Now it says:

我恢复中断,并触摸脚本文件,以便重新加载模块,然后重新加载。现在它说:

Attempt to reload MyPackage/Foo.pm aborted.
Compilation failed in require at E:/dev/test.pl line 4.

And even if I touch the script and the module, I cannot get it to reload correctly, except by restarting the web server.

即使我触摸脚本和模块,我也无法正确重新加载,除非重新启动Web服务器。

Breaking just the script itself (as opposed to the module) works fine: proper errors and changing it back results in it working again upon reload.

打破脚本本身(而不是模块)工作正常:正确的错误和更改它会导致它在重新加载时再次工作。

After each of these things I restarted the web server before testing:

在完成这些操作之后,我在测试之前重新启动了Web服务器:

  1. I've tried doing a trace, but the line that it continues to error out on is ModPerl/RegistryCooker.pm line 204, which is just the line that eval{}s the whole script.

    我已经尝试过跟踪,但是它继续出错的行是ModPerl / RegistryCooker.pm第204行,它只是eval {}整个脚本的行。

  2. I've tried changing "use warnings FATAL => 'all'" to just "use warnings" in the script and the module. Didn't make a difference.

    我已经尝试将“使用警告FATAL =>'all'”更改为脚本和模块中的“使用警告”。没有什么区别。

  3. I've tried disabling my custom $SIG{__DIE__} function. Didn't make a difference. (Well, only in where the error appeared, of course, but the errors generated were the same.)

    我已经尝试禁用我的自定义$ SIG {__ DIE__}函数。没有什么区别。 (当然,只有在出现错误的地方,但产生的错误是相同的。)

  4. Per the discussion link at the beginning, found that MaxRequestsPerChild has been 0 this whole time, and I tried ThreadsPerChild 1, but no difference. I tried MaxRequestsPerChild to 1, which solves the weird behaviours of this question, but restarts the web server after every single request:

    根据开头的讨论链接,发现MaxRequestsPerChild一直都是0,我试过ThreadsPerChild 1,但没有区别。我尝试将MaxRequestsPerChild设置为1,这解决了此问题的奇怪行为,但在每次请求后重新启动Web服务器:

    Child 7072: Process exiting because it reached MaxRequestsPerChild. Signaling the parent to restart a new child process.
    Parent: Received restart signal -- Restarting the server.
    

    This isn't a good solution, since I have a significant chunk of code that's run the first time a page is hit.

    这不是一个好的解决方案,因为我有一大堆代码在第一次命中页面时运行。

  5. Also per the discussion, I run httpd as a service, so I added -X in the service parameters window and hit Start, and it was still trying to start a full three minutes later (usually starts within 3 seconds.) Even got a timeout message. Killed process via task manager and verified I couldn't hit the page from a web browser. Started httpd -X from the command line. Still the same behaviour as at the top of this question. Also I found it odd that -X was not listed when I ran httpd -?. Maybe it's not available on the win32 MPM?

    同样根据讨论,我将httpd作为服务运行,所以我在服务参数窗口中添加-X并点击Start,它仍然尝试在三分钟后启动一整天(通常在3秒内启动。)甚至超时信息。通过任务管理器杀死进程并验证我无法从Web浏览器访问该页面。从命令行启动httpd -X。仍然与此问题顶部的行为相同。另外我发现在运行httpd时没有列出-X的奇怪 - ?也许它在win32 MPM上不可用?

  6. In that thread, David notes:

    在那篇帖子中,大卫指出:

    My experience troubleshooting this kind of issue has indicated that its likely that the package that was unloaded deleted a value stored in the package space of the module reloaded (probably set at BEGIN block time) that the subsequent require did not restore.

    我对此类问题进行故障排除的经验表明,卸载的软件包可能会删除存储在重新加载的模块的软件包空间中的值(可能设置为BEGIN块时间),后续需求没有恢复。

    But this isn't true of my code. The 'break the script' error I introduce is just adding an extra 'my $var' line above one that's already there, so that the second one will complain that it's already been declared.

    但我的代码并非如此。我介绍的'破坏脚本'错误只是在已经存在的那个上面添加了一个额外的'my $ var'行,所以第二个会抱怨它已经被声明了。

Is there no way to work on mod_perl2 modules without having the web server restart after every reload (whether automatically, via MaxRequestsPerChild, or manually, as before)?

没有办法在没有重新加载后重新加载Web服务器的mod_perl2模块(无论是自动,通过MaxRequestsPerChild,还是像以前一样手动)?

1 个解决方案

#1


Copy the sub to the script you're calling it from, and put this code before the copy:

将sub复制到您正在调用它的脚本,并将此代码放在副本之前:

package MyPackage::Foo;
no warnings 'redefine';

When you're done making changes, move the sub back to the actual module.

完成更改后,将子项移回实际模块。

#1


Copy the sub to the script you're calling it from, and put this code before the copy:

将sub复制到您正在调用它的脚本,并将此代码放在副本之前:

package MyPackage::Foo;
no warnings 'redefine';

When you're done making changes, move the sub back to the actual module.

完成更改后,将子项移回实际模块。