繁体   English   中英

如何从另一个进程调用正在运行的Perl进程中的方法?

[英]How can I call a method in a running Perl process from another process?

好的,所以,我得到了信号通过但由于某种原因,该过程在收到信号后存在。

如果我在创建套接字之前添加无限循环(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";

我不明白我是否误读了你的问题,或者你是否忽略了明显的问题。 我不会依赖信号来做这样的事情。

我不得不scriptA听插座并有scriptB发送邮件到scriptA (而不是信号)。 如果它收到正确的消息,它会将相关数据写出到与其连接的所有客户端。

如果在perl脚本中安装信号处理程序 ,则不必结束脚本。 (不要通过调用die退出处理程序)注意,您不需要发送SIGINT或SIGKILL,也可以发送SIGUSR1。

编辑你的kill命令的命令行后面有一个逗号,后面不应该有-USR1,(它是kill -USR1 4169)

编辑2当信号中断文件句柄的空数组时,while(can_read)循环可能存在。 您可以通过以下条件来防止这种情况:

while ((@read_ready = $sel->can_read) || 0 < $sel->count ) {

并更新循环以处理空的@ready数组。

只是为了扩展之前的答案/评论。 您可以为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的方法将是一个更好的选择,因为scriptA已经打开套接字。 为什么不让scriptB通过套接字与scriptA通信,并根据需要重定向控制流。

[编辑2]我看了一下can_read的底层IO :: Select代码,显然有一个select()调用来获取准备就绪的文件描述符。 在您的情况下,由于超时值为undef,因此select调用块。 根据perldoc上的文档 ,选择在信号处理程序依赖于实现后重新启动。 在您的情况下(和我的),select()调用'not'重新启动。 因此,空数组返回到while条件检查,导致服务器退出。

快速解决这个问题的是 -

while ((@read_ready = $sel->can_read) || 1) {
    next if @read_ready == 0;
    ...
}

这就是我考虑废弃一切并重新思考设计流程的重点。

通过使用信号,您可以引入一些微妙的错误,具体取决于在传递信号时scriptA正在执行的操作。 相反,我建议您在scriptA mainloop中添加一个检查来查找来自scriptB通信。

我还建议这种通信采用两个脚本打开的命名信号量的形式。 scriptB可以在适当的时候发布信号量, scriptA可以在其循环中的某个点执行非阻塞$sem->trywait() 有关确切语法的更多信息,请参见POSIX :: RT :: Semaphore

使用此方法, scriptA可以决定何时适合处理来自scriptB的指令,并避免scriptB程序被异步信号传递中断而引起的所有令人讨厌的问题。

有关更多信号及其细微之处,请查看Perl CookbookProgramming Perl

虽然这可能不是您的要求的一部分,但如果您想调用多个方法,则可以设置远程过程调用(RPC)接口。 Event :: RPC之类的东西,但这可能是矫枉过正的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM