loleaflet/src/core/Socket.js | 30 ++++++++++++++++++++++++++++ wsd/LOOLWSD.cpp | 45 ++++++++++++++++++++++++++++++++++++++----- wsd/protocol.txt | 4 ++- 3 files changed, 73 insertions(+), 6 deletions(-)
New commits: commit 2b9ea3d4a68e7483e837426bda178e489ae7a4b2 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Sun Nov 27 19:11:30 2016 -0500 loolwsd: notify clients before recycling wsd Change-Id: Ib2733a6af1c27fe39c54f5c3bc6f5bd3acb72a2b Reviewed-on: https://gerrit.libreoffice.org/31298 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js index eab6ca8..40c4cf2 100644 --- a/loleaflet/src/core/Socket.js +++ b/loleaflet/src/core/Socket.js @@ -195,6 +195,36 @@ L.Socket = L.Class.extend({ else if (textMsg === 'shuttingdown') { msg = _('Server is shutting down for maintenance (auto-saving)'); } + else if (textMsg === 'recycling') { + msg = _('Server is recycling and will be available shortly'); + + this._map._active = false; + + // Prevent reconnecting the world at the same time. + var min = 5000; + var max = 10000; + var timeoutMs = Math.floor(Math.random() * (max - min) + min); + + socket = this; + map = this._map; + vex.timer = setInterval(function() { + if (socket.connected()) { + // We're connected: cancel timer and dialog. + clearTimeout(vex.timer); + if (vex.dialogID > 0) { + var id = vex.dialogID; + vex.dialogID = -1; + vex.close(id); + } + return; + } + + try { + socket.initialize(map); + } catch (error) { + } + }, timeoutMs); + } // Close any open dialogs first. if (vex.dialogID > 0) { diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp index 25a4bab..6b143a4 100644 --- a/wsd/LOOLWSD.cpp +++ b/wsd/LOOLWSD.cpp @@ -175,6 +175,10 @@ static std::atomic<int> OutstandingForks(1); // Forkit always spawns 1. static std::map<std::string, std::shared_ptr<DocumentBroker>> DocBrokers; static std::mutex DocBrokersMutex; +/// Used when shutting down to notify them all that the server is recycling. +static std::vector<std::shared_ptr<LOOLWebSocket>> ClientWebSockets; +static std::mutex ClientWebSocketsMutex; + #if ENABLE_DEBUG static int careerSpanSeconds = 0; #endif @@ -983,6 +987,13 @@ private: } } + if (SigUtil::isShuttingDown()) + { + std::lock_guard<std::mutex> lock(ClientWebSocketsMutex); + LOG_TRC("Capturing Client WS for [" << id << "]"); + ClientWebSockets.push_back(ws); + } + LOOLWSD::dumpEventTrace(docBroker->getJailId(), id, "EndSession: " + uri); LOG_INF("Finishing GET request handler for session [" << id << "]."); } @@ -1011,11 +1022,14 @@ private: } else { - // something wrong, with internal exceptions - LOG_TRC("Abnormal close handshake."); - session->closeFrame(); - // FIXME: handle exception thrown from here ? ... - ws->shutdown(WebSocket::WS_ENDPOINT_GOING_AWAY); + if (!SigUtil::isShuttingDown()) + { + // something wrong, with internal exceptions + LOG_TRC("Abnormal close handshake."); + session->closeFrame(); + // FIXME: handle exception thrown from here ? ... + ws->shutdown(WebSocket::WS_ENDPOINT_GOING_AWAY); + } } LOG_INF("Finished GET request handler for session [" << id << "]."); @@ -2149,6 +2163,27 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/) FileUtil::removeFile(path, true); } + if (SigUtil::isShuttingDown()) + { + // At this point there should be no other thread, but... + std::lock_guard<std::mutex> lock(ClientWebSocketsMutex); + + LOG_INF("Notifying clients that we are recycling."); + static const std::string msg("close: recycling"); + for (auto& ws : ClientWebSockets) + { + try + { + ws->sendFrame(msg.data(), msg.size()); + ws->shutdown(WebSocket::WS_ENDPOINT_GOING_AWAY); + } + catch (const std::exception& ex) + { + LOG_ERR("Error while notifying client of recycle: " << ex.what()); + } + } + } + // Finally, we no longer need SSL. if (LOOLWSD::isSSLEnabled()) { diff --git a/wsd/protocol.txt b/wsd/protocol.txt index 2ebdc33..b6d55ef 100644 --- a/wsd/protocol.txt +++ b/wsd/protocol.txt @@ -248,11 +248,13 @@ close: <reason> ability to kill all other sessions if EnableOwnerTermination flag in WOPI CheckFileInfo is 'true' (assumed to be 'false' by default). - * shuttingdown - Sent when the server is going down in a graceful fashion. The server doesn't disconnect from clients yet, but starts saving document and tearing down internals. + * recycling - The last message sent from the server when it is gracefully + shutting down to let clients know they can try connecting + after a short interval. getchildid: id=<id> _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits