如何从一个文件描述符创建一个可用的IO::Socket::INET套接字对象?
问题是 Bad arg length for Socket::unpack_sockaddr_in,见下文。
重现步骤
文件 /tmp/demo/app.psgi
use 5.042;
use strictures;
use Plack::Request qw();
use experimental 'signatures';
my $app = sub($env) {
my $req = Plack::Request->new($env);
return $req->new_response(200, ['Content-Type' => 'text/plain'], ['Hello world'])->finalize;
};
文件 ~/.config/systemd/user/demo.service,将 … 替换为指向 plackup 的绝对路径
[Unit]
Description=Socket-activated hello world service
Requires=demo.socket
After=network.target
[Service]
ExecStart=…perl/5.42.2/bin/plackup -a /tmp/demo/app.psgi
Type=simple
文件 ~/.config/systemd/user/demo.socket
[Unit]
Description=Socket for hello world service activation
PartOf=demo.service
[Socket]
ListenStream=5000
NoDelay=true
Backlog=128
[Install]
WantedBy=sockets.target
对Plack-1.0054应用补丁
diff --git a/lib/HTTP/Server/PSGI.pm b/lib/HTTP/Server/PSGI.pm
index 225d4ca..f060463 100644
--- a/lib/HTTP/Server/PSGI.pm
+++ b/lib/HTTP/Server/PSGI.pm
@@ -90,6 +90,12 @@ sub prepare_socket_class {
sub setup_listener {
my $self = shift;
+ # TO DO: also handle LISTEN_PID LISTEN_PIDFDID
+ if ($ENV{LISTEN_FDS} && 1 == $ENV{LISTEN_FDS}) {
+ $self->{listen_sock} ||= IO::Socket::INET->new_from_fd(3, 'r+');
+ goto DONE;
+ }
+
$self->{listen_sock} ||= do {
my %args = (
Listen => SOMAXCONN,
@@ -104,6 +110,7 @@ sub setup_listener {
or die "failed to listen to port $self->{port}: $!";
};
+DONE:
$self->{server_ready}->({ %$self, proto => $self->{ssl} ? 'https' : 'http' });
}
- 应用补丁,并把修补后的Plack安装在
app.psgi可以使用的路径上 - 让端口5000可用(也可能是已有的Plack应用占用了端口?)
- 运行
systemctl --user daemon-reload - 运行
systemctl --user enable --now demo.socket
观察到的问题
运行 xh -v :5000,或使用任意其他HTTP客户端向 GET http://localhost:5000 发送请求,均无响应。
journalctl --user -e -u demo -f 显示错误:
systemd: Started Socket-activated hello world service.
plackup: HTTP::Server::PSGI: Accepting connections at http://0:5000/
plackup: Bad arg length for Socket::unpack_sockaddr_in, length is 28, should be 16 at …perl/5.42.2/lib/5.42.2/x86_64-linux-ld/Socket.pm line 858.
systemd: demo.service: Main process exited, code=exited, status=29/n/a
systemd: demo.service: Failed with result 'exit-code'.
重新开始:systemctl --user stop demo.service;systemctl --user restart demo.socket
预期结果
HTTP请求完成。
相关信息
在dist IO:new_from_fd 文档,new_from_fd 测试
清理系统
systemctl --user disable --now demo.socket
rm ~/.config/systemd/user/demo.{service,socket} /tmp/demo/app.psgi
# rm -rf …Plack-1.055
systemctl --user daemon-reload
解决方案
... Bad arg length for Socket::unpack_sockaddr_in, length is 28, should be 16
这看起来不是你得到的IPv4套接字,而是一个IPv6套接字。这意味着你需要使用IO::Socket::IP,而不是IO::Socket::INET。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。