NAME
Linux::Event::Kernel::Inotify::Watch - One filesystem watch owned by an Inotify object
SYNOPSIS
use Linux::Event::Loop;
use Linux::Event::Kernel::Inotify;
my $loop = Linux::Event::Loop->new;
my $inotify = Linux::Event::Kernel::Inotify->new;
my $watch = $inotify->watch(
'/srv/data',
on_modify => sub ($event) {
say $event->path . ' changed';
},
);
$loop->add($inotify);
$loop->run_for(10);
$watch->cancel;
DESCRIPTION
Linux::Event::Kernel::Inotify::Watch represents one logical filesystem subscription created by:
$inotify->watch(...)
Applications do not normally construct Watch objects directly.
The parent Linux::Event::Kernel::Inotify object owns the Linux inotify instance.
Each Watch represents one application-level subscription within that parent.
For example:
my $first = $inotify->watch(
'/srv/data',
on_modify => sub ($event) {
log_change($event->path);
},
);
my $second = $inotify->watch(
'/srv/data',
on_modify => sub ($event) {
$changes++;
},
);
$first and $second are separate logical Watches even if Linux can represent both through one underlying kernel watch descriptor.
Each can be cancelled independently.
WATCH CREATION
Watch objects are returned by the parent:
my $watch = $inotify->watch(
$path,
on_modify => sub ($event) {
...
},
);
See Linux::Event::Kernel::Inotify for the supported filesystem callbacks and watch options.
PENDING AND ACTIVE WATCHES
If the parent Inotify object is detached when watch is called:
my $inotify = Linux::Event::Kernel::Inotify->new;
my $watch = $inotify->watch(
'/srv/data',
on_modify => sub ($event) {
...
},
);
the Watch begins in the pending state.
The logical subscription has been recorded, but the kernel watch does not yet exist.
When the parent is attached:
$loop->add($inotify);
the Watch becomes active.
If the parent is already active when watch is called, the new Watch is activated before watch returns successfully.
CANCELLING A WATCH
cancel
$watch->cancel;
Cancel this logical filesystem subscription.
Cancellation is immediate and terminal.
After cancel returns, no later callback is delivered to that Watch.
This includes an IN_IGNORED notification caused by Linux removing the underlying kernel watch.
cancel returns the Watch object.
Calling it again is harmless.
CANCELLING ONE OF SEVERAL WATCHES
Several logical Watches may refer to the same underlying filesystem object.
For example:
my $logger = $inotify->watch(
'/srv/data',
on_modify => sub ($event) {
log_change($event->path);
},
);
my $counter = $inotify->watch(
'/srv/data',
on_modify => sub ($event) {
$modified++;
},
);
Cancelling:
$logger->cancel;
does not cancel $counter.
Linux::Event updates the shared kernel subscription as necessary to preserve the events still required by surviving Watches.
PATH
path
my $path = $watch->path;
Return the absolute path captured when the Watch was created.
Relative input paths are converted to absolute paths by the parent watch method.
Therefore:
my $watch = $inotify->watch(
'log.txt',
on_modify => sub ($event) {
...
},
);
chdir '/tmp';
does not change what $watch->path refers to.
PARENT INOTIFY OBJECT
inotify
my $inotify = $watch->inotify;
Return the parent Linux::Event::Kernel::Inotify object while that object still exists.
This can also be reached from an event callback:
on_modify => sub ($event) {
my $watch = $event->watch;
my $inotify = $watch->inotify;
}
The parent relationship is weak internally, so a Watch does not keep an otherwise unused parent Inotify object alive by itself.
STATE
state
my $state = $watch->state;
A Watch can pass through several states.
pending
pending means the Watch has been configured on a detached Inotify parent but has not yet been installed in the kernel.
active
active means the Watch is currently able to receive filesystem events.
cancelled
cancelled means the application explicitly called cancel.
ignored
ignored means Linux invalidated the underlying kernel watch.
closed
closed means the parent Inotify object was closed.
failed
failed means activation of a Watch on an already-active parent failed.
Managed-fork handling can also produce terminal states such as not_inherited and moved.
IS THE WATCH ACTIVE?
is_active
if ($watch->is_active) {
...
}
Return true only while the Watch state is active.
A pending Watch is not yet active.
IS THE WATCH TERMINAL?
is_terminal
if ($watch->is_terminal) {
...
}
Return false for pending and active.
Return true for terminal states such as:
cancelled
ignored
closed
failed
not_inherited
moved
A terminal Watch cannot later be reactivated.
WATCH EVENTS
Filesystem callbacks receive a Linux::Event::Kernel::Inotify::Event rather than the Watch directly:
my $watch = $inotify->watch(
'/srv/data',
on_modify => sub ($event) {
say $event->path;
},
);
The Event identifies the Watch that received it:
my $watch = $event->watch;
This is particularly useful when the same callback is shared by several Watches.
PARENT CLOSE
Closing the parent:
$inotify->close;
makes all of its remaining Watch objects terminal.
No callbacks are delivered to them afterward.
The Watch state becomes closed unless another terminal lifecycle state was already established.
LOOP-AWARE FORKING
Watch lifecycle follows the disposition of its parent Linux::Event::Kernel::Inotify object.
If the parent is cloned:
my $pid = $loop->fork(
clone => [$inotify],
);
the child recreates an independent Inotify instance and corresponding active Watch subscriptions.
If the parent is moved:
my $pid = $loop->fork(
move => [$inotify],
);
the parent-side Watch becomes terminal with state moved after the move commits.
If the parent is omitted from the managed-fork disposition lists, the child copy becomes terminal with state not_inherited.
Watch objects are not listed separately in Loop->fork disposition arrays; their lifecycle belongs to the parent Inotify resource.
SEE ALSO
Linux::Event, Linux::Event::Loop, Linux::Event::Kernel::Inotify, Linux::Event::Kernel::Inotify::Event.