154 else |
155 else |
155 log("error", "Console is enabled, but the console module appears not to be loaded"); |
156 log("error", "Console is enabled, but the console module appears not to be loaded"); |
156 end |
157 end |
157 end |
158 end |
158 |
159 |
159 -- setup error handling |
160 -- Global function to initiate prosody shutdown |
|
161 function prosody_shutdown(reason) |
|
162 log("info", "Shutting down: %s", reason or "unknown reason"); |
|
163 server.setquitting(true); |
|
164 end |
|
165 |
|
166 -- Catch global accesses -- |
160 local locked_globals_mt = { __index = function (t, k) error("Attempt to read a non-existent global '"..k.."'", 2); end, __newindex = function (t, k, v) error("Attempt to set a global: "..tostring(k).." = "..tostring(v), 2); end } |
167 local locked_globals_mt = { __index = function (t, k) error("Attempt to read a non-existent global '"..k.."'", 2); end, __newindex = function (t, k, v) error("Attempt to set a global: "..tostring(k).." = "..tostring(v), 2); end } |
161 |
168 |
162 function unlock_globals() |
169 function unlock_globals() |
163 setmetatable(_G, nil); |
170 setmetatable(_G, nil); |
164 end |
171 end |
165 |
172 |
166 function lock_globals() |
173 function lock_globals() |
167 setmetatable(_G, locked_globals_mt); |
174 setmetatable(_G, locked_globals_mt); |
168 end |
175 end |
169 |
176 |
|
177 -- And lock now... |
170 lock_globals(); |
178 lock_globals(); |
171 |
179 |
172 eventmanager.fire_event("server-started"); |
180 eventmanager.fire_event("server-started"); |
173 |
181 |
174 local quitting; |
182 -- Error handler for errors that make it this far |
175 while not quitting do |
183 local function catch_uncaught_error(err) |
176 xpcall(server.loop, function (err) |
184 if err:match("%d*: interrupted!$") then |
177 if err:match("%d*: interrupted!$") then |
185 return "quitting"; |
178 quitting = true; |
186 end |
179 return; |
187 |
180 end |
188 log("error", "Top-level error, please report:\n%s", tostring(err)); |
181 |
189 local traceback = debug.traceback("", 2); |
182 log("error", "Top-level error, please report:\n%s", tostring(err)); |
190 if traceback then |
183 |
191 log("error", "%s", traceback); |
184 local traceback = debug.traceback("", 2); |
192 end |
185 if traceback then |
193 |
186 log("error", "%s", traceback); |
194 eventmanager.fire_event("very-bad-error", "*", err, traceback); |
187 end |
195 end |
188 |
196 |
189 eventmanager.fire_event("very-bad-error", "*", err, traceback); |
197 while select(2, xpcall(server.loop, catch_uncaught_error)) ~= "quitting" do |
190 end); |
198 socket.sleep(0.2); |
191 end |
199 end |
|
200 |
|
201 -- Ok, we're quitting I know, but we |
|
202 -- need to do some tidying before we go :) |
|
203 server.setquitting(false); |
|
204 |
|
205 for hostname, host in pairs(hosts) do |
|
206 if host.sessions then |
|
207 for username, user in pairs(host.sessions) do |
|
208 for resource, session in pairs(user.sessions) do |
|
209 log("debug", "Closing connection for %s@%s/%s", username, hostname, resource); |
|
210 session:close("system-shutdown"); |
|
211 end |
|
212 end |
|
213 end |
|
214 |
|
215 if host.s2sout then |
|
216 for remotehost, session in pairs(host.s2sout) do |
|
217 if session.close then |
|
218 session:close("system-shutdown"); |
|
219 else |
|
220 log("warn", "Unable to close outgoing s2s session to %s, no session:close()?!", remotehost); |
|
221 end |
|
222 end |
|
223 end |
|
224 end |
|
225 |
|
226 server.closeall(); |