Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

file system event watching fixes #4210

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,7 @@ export
truncate,
UV_READABLE,
UV_WRITABLE,
watch_file,
WindowsRawSocket,
write,
writecsv,
Expand Down
19 changes: 12 additions & 7 deletions base/poll.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ function close(t::FileMonitor)
end
end

# Polling event flags
const UV_READABLE = 1
const UV_WRITABLE = 2
# Non-polling event flags
const UV_RENAME = 1
const UV_CHANGE = 2

convert(::Type{Int32},fd::RawFD) = fd.fd

Expand Down Expand Up @@ -237,14 +241,14 @@ function stop_watching(t::PollingFileWatcher)
end

function _uv_hook_fseventscb(t::FileMonitor,filename::Ptr,events::Int32,status::Int32)
fname = bytestring(convert(Ptr{Uint8},filename)) # seems broken at the moment - got NULL
if isa(t.cb,Function)
# bytestring(convert(Ptr{Uint8},filename)) - seems broken at the moment - got NULL
t.cb(status, events, status)
if status == -1
notify_error(t.notify,UVError("FileMonitor",status))
else
notify(t.notify,events)
end
t.cb(fname, events, status)
end
if status < 0
notify_error(t.notify,(UVError("FileMonitor",status), fname, events))
else
notify(t.notify,(status, fname, events))
end
end

Expand Down Expand Up @@ -282,6 +286,7 @@ function poll_file(s, interval_seconds::Real, seconds::Real)
wait(wt) == :poll
end

watch_file(s; poll=false) = watch_file(false, s, poll=poll)
function watch_file(cb, s; poll=false)
if poll
pfw = PollingFileWatcher(cb,s)
Expand Down
4 changes: 4 additions & 0 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,10 @@ Network I/O
Create a TcpServer on any port, using hint as a starting point. Returns a tuple of the actual port that the server
was created on and the server itself.

.. function:: watch_file(cb=false, s; poll=false)

Watch file or directory ``s`` and run callback ``cb`` when ``s`` is modified. The ``poll`` parameter specifies whether to use file system event monitoring or polling. The callback function ``cb`` should accept 3 arguments: ``(filename, events, status)`` where ``filename`` is the name of file that was modified, ``events`` can be ``UV_CHANGE`` or ``UV_RENAME`` when using file system event monitoring, or ``UV_READABLE`` or ``UV_WRITABLE`` when using polling, and ``status`` is always 0. Pass ``false`` for ``cb`` to not use a callback function.

.. function:: poll_fd(fd, seconds::Real; readable=false, writable=false)

Poll a file descriptor fd for changes in the read or write availability and with a timeout given by the second argument.
Expand Down
14 changes: 14 additions & 0 deletions test/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,27 @@ function test_monitor(slval)
close(fm)
end

function test_monitor_wait(tval)
fm = watch_file(file)
@async begin
sleep(tval/10_000)
f = open(file,"a")
write(f,"Hello World\n")
close(f)
end
fname, events = wait(fm)
@test fname == basename(file)
@test events == Base.UV_CHANGE
end

# Commented out the tests below due to issues 3015, 3016 and 3020
test_timeout(0.1)
test_timeout(1)
test_touch(0.1)
test_touch(1)
test_monitor(1)
test_monitor(0.1)
test_monitor_wait(0.1)

##########
# mmap #
Expand Down