好的,所以,我得到了信号,但由于某种原因,该过程在收到信号后存在。
如果我在创建套接字之前添加无限循环(while(1)),那么它按规定工作。 所以......当我发出kill命令时,套接字代码中的某些东西就会退出。
我看不出它会是什么。如果没有kill,进程就会无限期地接受连接并向客户端发送消息。为什么kill(以及随后的变量的增量)会引发套接字退出循环并让进程结束?
套接字代码位于......
之下[再次编辑]
$SIGNAL = 0;
sub sigHandler{
#&logData("SIGNALED");
$SIGNAL++ ;
}
$SIG{"USR1"}=\&sigHandler;
# Create a new socket, on port 9999
my $PORT = 9999;
print ("opening connection on port $PORT");
$lsn = new IO::Socket::INET(Listen => 1,
LocalPort => $PORT,
Reuse => 1,
Proto => 'tcp' );
#or die ("Couldn't start server: $!");
# Create an IO::Select handler
$sel = new IO::Select( $lsn );
# Close filehandles
close(STDIN); close(STDOUT);
warn "Server ready. Waiting for connections . . . on \n";
# Enter into while loop, listening to the handles that are available.
# this SHOULD be an infinite loop... I don't see why it would eval to false when
# I send a signal to increment $SIGNAL by one.
while( @read_ready = $sel->can_read ) {
$MESSAGE = 0;
$fh = $read_ready[0];
# Create a new socket
if($fh == $lsn) {
$new = $lsn->accept;
$sel->add($new);
push( @data, fileno($new) . " has joined.");
warn "Connection from " . $new->peerhost . ".\n";
}
# Handle connection
else {
$input = <$fh>;
chomp $input;
warn "GOT INPUT '$input'\n";
if($input eq "<policy-file-request/>"){
$MESSAGE =
qq~<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" to-ports="*"/>
</cross-domain-policy>\0~;
$SIGNAL++;
}
if ( $input eq '') {#disconnection notification by client
warn "Disconnection from " . $new->peerhost . ".\n";
$sel->remove($fh);
$fh->close;
}
if ( $input eq 'READY'){
warn "CLIENT READY = 1\n";
$CLIENT_READY = 1;
}
}
# Write to the clients that are available
foreach $fh ( @write_ready = $sel->can_write(0) ) {
if($MESSAGE == 0){
#set message here based on criteria
$MESSAGE = "UPDATE";
}
warn "outside send if\n";
if($CLIENT_READY == 1 && $SIGNAL > 0){
warn ("sending $MESSAGE to $fh\n");
$CLIENT_READY = 0;
$SIGNAL--;
print $fh "$MESSAGE\0" or warn "can't send message to $fh";
}
}
}
warn "Server ended.\n";
答案 0 :(得分:6)
我不明白我是否误读了你的问题,或者你是否忽略了明显的问题。我不会依赖信号来做这样的事情。
我有scriptA
听取套接字并让scriptB
向scriptA
发送消息(而不是信号)。如果它收到正确的消息,它会将相关数据写出到与其连接的所有客户端。
答案 1 :(得分:5)
如果在perl脚本中安装signal handler,则不必结束脚本。 (不要通过调用die
退出处理程序)注意,您不需要发送SIGINT或SIGKILL,也可以发送SIGUSR1。
修改强> kill命令的命令行后面有一个逗号-USR1,不应该在那里,(它是kill -USR1 4169)
编辑2 while(can_read)循环可能在它被信号中断时接收到空文件句柄数组时存在。您可以通过以下条件来防止这种情况:
while ((@read_ready = $sel->can_read) || 0 < $sel->count ) {
并更新循环以处理空的@ready
数组。
答案 2 :(得分:3)
只是扩展之前的答案/评论。您可以为SIGUSR1 / 2编写一个处理程序来捕获外部信号并在脚本中运行相应的子例程。所有scriptB要做的就是调用“kill -SIGUSR [12] {pidof scriptA}”来调用scriptA中的处理程序。
示例信号处理程序类似于 -
#!/usr/bin/perl
use strict;
use warnings;
$SIG{USR1} = sub { print "Caught USR1\n"; };
$SIG{USR2} = sub { print "Caught USR2\n"; };
while (sleep 5) {}
确保您的信号处理子程序中没有模具/退出调用,以便在处理完呼叫后程序可以不间断地继续。
[编辑] 在重新审视这个问题后,我认为Noufal的approach将是一个更好的选择,因为scriptA已经打开套接字。为什么不让scriptB通过套接字与scriptA进行通信,并根据需要重定向控制流。
[EDIT2] 我看了一下can_read的底层IO :: Select代码,显然有一个select()调用来获取准备就绪的文件描述符。在您的情况下,由于超时值为undef,因此select调用块。根据perldoc上的documentation,选择在信号处理程序依赖于实现后重新启动。在您的情况下(和我的),select()调用'not'重新启动。因此,空数组返回到while条件检查,导致服务器退出。
快速解决这个问题的方法是 -
while ((@read_ready = $sel->can_read) || 1) {
next if @read_ready == 0;
...
}
这是我考虑废弃所有内容并重新思考设计流程的重点。
答案 3 :(得分:2)
通过使用信号,您可以引入一些微妙的错误,具体取决于信号传递时scriptA
正在做什么。相反,我建议您在scriptA
主循环中添加一个检查,以查找来自scriptB
的通信。
我还建议这种通信采用两个脚本打开的命名信号量的形式。 scriptB
可以在适当的时候发布信号量,scriptA
可以在其循环中的某个时刻执行非阻塞$sem->trywait()
。有关确切语法的详细信息,请参阅POSIX::RT::Semaphore。
使用此方法,scriptA
可以决定何时处理来自scriptB
的指令,并避免因异步信号传递而中断子程序而引起的所有令人讨厌的问题。 / p>
有关更多信号及其细微之处,请查看Perl Cookbook和Programming Perl。
答案 4 :(得分:1)
虽然这可能不是您要求的一部分,但如果您想调用多个方法,则可以设置远程过程调用(RPC)接口。像Event::RPC这样的东西,但这可能有点矫枉过正。