-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile_watcher.lua
More file actions
139 lines (109 loc) · 3.3 KB
/
file_watcher.lua
File metadata and controls
139 lines (109 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
---
-- @copyright (c) 2016 Russell Haley
-- @license FreeBSD License. See License.txt
local strict = require "strict"
local cqueues = require "cqueues"
local notify = require "cqueues.notify"
local signal = require "cqueues.signal"
local auxlib = require "cqueues.auxlib"
local thread = require"cqueues.thread"
local assert = auxlib.assert -- cqueues doesn't yet do idiomatic error tuples
local progname = arg and arg[0] or "notify"
local function Notify(...)
local msg = string.format(...)
for ln, nl in msg:gmatch "([^\n]*)(\n?)" do
if #ln > 0 or #nl > 0 then
io.stderr:write(string.format("%s: %s\n", progname, ln))
end
end
end
local function parsepath(path)
local isabs = path:match "^/" and true or false
local name = {}
for fname in path:gmatch "[^/]+" do
name[#name + 1] = fname
end
return isabs, name
end
local function dirname(path)
local isabs, name = parsepath(path)
name[#name] = nil
if isabs then
return "/" .. table.concat(name, "/")
elseif #name == 0 then
return "."
else
return table.concat(name, "/")
end
end
local function basename(path)
local isabs, name = parsepath(path)
local base = name[#name]
if base then
return base
elseif isabs then
return "/"
else
return "."
end
end
local mainloop = cqueues.new()
local path = ... or "logtesting.log"
mainloop:wrap(function()
Notify("watching %s", path)
local nfy = assert(notify.opendir(dirname(path), notify.ALL))
assert(nfy:add(basename(path)))
for flags, name in nfy:changes() do
-- ignore changes to containing directory
if name == basename(path) then
for flag in notify.flags(flags) do
Notify("%s %s", name, notify[flag])
end
end
end
end)
-- Waits on signals
mainloop:wrap(function()
signal.block(signal.SIGINT, signal.SIGHUP)
local signo = signal.listen(signal.SIGINT, signal.SIGHUP):wait()
Notify("exiting on signal (%s)", signal.strsignal(signo))
os.exit(0)
end)
--- Implement a dead-man switch in case a bug in our code causes the main
-- loop to stall.
--
-- ------------------------------------------------------------------------
mainloop:wrap(function()
local thr, pipe = thread.start(function(pipe)
local cqueues = require"cqueues"
local sleep = cqueues.sleep
local poll = cqueues.poll
local watchdog = cqueues.new()
watchdog:wrap(function()
cqueues.sleep(10)
-- try to drain socket so we don't get stale alive
-- tokens on successive iterations.
while pipe:recv(-32) do
print("muchas Gracisas")
poll(pipe, 10)
end
io.stderr:write"main thread unresponsive\n"
os.exit(false)
end)
local ok, why = watchdog:loop()
io.stderr:write(string.format("dead-man thread failed: %s\n", why or "unknown error"))
os.exit(false)
end)
mainloop:wrap(function()
while true do
cqueues.sleep(5)
assert(pipe:write"!\n")
Notify("Ei, carumba!")
end
end)
end)
--cqueues.poll({pollfd = myfd; events = "p"})
for err in mainloop:errors() do
Notify("%s", err)
os.exit(1)
end