multithreading - Linux::Inotify2 和线程

标签 multithreading perl inotify

我尝试使用 Linxu::Inotify2 - 但不是在线程中。

如果我在程序中有线程,那么我会因 Inotifys 读取而崩溃。 如果我不使用线程,一切都很好。

这里有一个小示例,应该可以说明问题。

use strict;
use warnings;
use threads;
use Linux::Inotify2;

my $X = 0;  # terminate the thread: 0=nothing, 1=detach, 2=join

STDOUT->autoflush ();
my $ino = new Linux::Inotify2 ();

$ino->blocking (0);
$ino->watch (".", IN_MODIFY | IN_ATTRIB | IN_CREATE) or die "error";

my @ls = ();   # for save threads if $X == 2
for (my $i=0;;$i++)
{
    my $th = threads->create (sub { print "\nTH". shift; }, $i);  # just to have threads; do nothing
    if ($X == 1)
    {
        $th->detach ();     # detach the thread
    }
    elsif ($X == 2)
    {
        push (@ls, $th);    # save for joining after thread finished
    }

    my @events = $ino->read ();   # *** CRASH if $X = 1 or 2
    if ($X == 2)
    {
        foreach (@ls)
        {
            if ($_->is_joinable ())
            {
                $_->join ();
            }
        }
    }

    sleep (1);
}

如果我将 $X 设置为 0,它将起作用。 如果我将它设置为 1 或 2,则会出现运行时错误。

Linux::Inotify2: read error while reading events at /usr/local/lib/x86_64-linux-gnu/perl/5.26.0/Linux/Inotify2.pm line 266.

这是为什么?

编辑

我简化了示例以更好地了解问题。

use strict;
use warnings;
use threads;
use Linux::Inotify2;

STDOUT->autoflush ();
my $ino = new Linux::Inotify2 ();

$ino->blocking (0);
$ino->watch (".", IN_CREATE | IN_DELETE) or die "error";

my $th = threads->create (sub {  });
$th->join ();

print "\nINO: ".$ino->poll();

去掉join就ok了,保留join就会失败。

最佳答案

以下示例实现了 zdim 的想法,zdim 提出使用事件循环和 poll() 而不是 read()。它是在 CentOS 7 上使用 Perl 5.16.2 和 Linux-Inotify2 v1.22 开发的。

程序生成一个线程来监视 /tmp 目录。您可以通过触摸和删除文件来测试它:touch/tmp/1/tmp/2 && rm/tmp/1/tmp/2

#!/usr/bin/env perl

use warnings FATAL => 'all';
use strict;
use threads;

threads->new(\&_eventListener, '/tmp')->join();

sub _eventListener {
  my ($path) = @_;

  require Linux::Inotify2;
  Linux::Inotify2->import(qw(IN_CREATE IN_DELETE IN_DELETE_SELF));

  my $fsEventListener = Linux::Inotify2->new() or 
    die('Cannot register Linux::Inotify2, stopped');

  $fsEventListener->watch(
    $path, 
    IN_CREATE() | IN_DELETE() | IN_DELETE_SELF(), 
    \&_watchCallback
  ) or die("Watch creation failed. '$!'");

  $fsEventListener->blocking(undef);

  while(1) {
    $fsEventListener->poll();
    sleep 1;
  }

  return;
}

sub _watchCallback {
  my ($e) = @_;

  printf STDOUT "Receive event '0x%04x' for file '%s'\n", $e->mask(), $e->fullname();

  return;
}

关于multithreading - Linux::Inotify2 和线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48589845/

相关文章:

java线程如何实现并发

linux - 获取错误 install_driver(Oracle) 失败 : Can't load '/usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/DBD/Oracle/Oracle.so'

c++ - 类似于内核版本 2.6.9(或更低版本)的 inotify 的类似工具

java - 方法局部内部类作用域

python - 创建大量对象(神经元)并使用字典随机连接

Perl 和服务器-客户端套接字

perl DBI 和准备好的语句名称冲突

c++ - 使用 stat 检测文件是否存在(慢?)

linux - 如何监控进程工作目录的变化?

Java - 在单独的线程中为每个客户端提供服务的服务器?