bgsave: detect crashed bgsave process, and/or early termination.
Warn, flag save as failed, and disable bgsave in these cases, perhaps we will not crash main kit process next time around. Signed-off-by: Michael Meeks <michael.meeks@collabora.com> Change-Id: Ia4f3d079a5503739efc11e408ed431c3b652860bpull/9099/head
parent
cf516d2ab1
commit
bb7e7857ac
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "Kit.hpp"
|
||||
#include "KitQueue.hpp"
|
||||
#include "ChildSession.hpp"
|
||||
#include "KitWebSocket.hpp"
|
||||
|
||||
using Poco::Exception;
|
||||
|
@ -226,24 +227,31 @@ BgSaveChildWebSocketHandler::~BgSaveChildWebSocketHandler()
|
|||
|
||||
// Kit handler for messages from transient background save Kit
|
||||
|
||||
void BgSaveParentWebSocketHandler::terminateSave(const std::string &session, const std::string &reason)
|
||||
void BgSaveParentWebSocketHandler::terminateSave(const std::string &reason)
|
||||
{
|
||||
LOG_WRN("terminating bgsave: " << reason);
|
||||
|
||||
// next time we get a non-background save.
|
||||
_document->disableBgSave("on unexpected jsdialog");
|
||||
LOG_TRC("terminating bgsave: " << reason);
|
||||
|
||||
// Hard terminate the bgsave child
|
||||
sendMessage("exit");
|
||||
shutdown(true, "unexpected jsdialog");
|
||||
|
||||
reportFailedSave(reason);
|
||||
}
|
||||
|
||||
void BgSaveParentWebSocketHandler::reportFailedSave(const std::string &reason)
|
||||
{
|
||||
// next time we get a non-background save.
|
||||
_document->disableBgSave(reason);
|
||||
|
||||
// Synthesize a failed save result
|
||||
// FIXME: could this allow another new manual save to race against the ongoing bgsave ?
|
||||
// either way - that's better than hanging and blocking if we get interactive dialogs on save.
|
||||
std::string saveFailed = session + " unocommandresult: { \"commandName\": \".uno:Save\", \"success\": false }";
|
||||
std::string saveFailed = "client-" + _session->getId() +
|
||||
" unocommandresult: { \"commandName\": \".uno:Save\", \"success\": false }";
|
||||
_document->sendFrame(saveFailed.c_str(), saveFailed.size(), WSOpCode::Text);
|
||||
|
||||
_document->updateModifiedOnFailedBgSave();
|
||||
_saveCompleted = true;
|
||||
}
|
||||
|
||||
void BgSaveParentWebSocketHandler::handleMessage(const std::vector<char>& data)
|
||||
|
@ -266,7 +274,7 @@ void BgSaveParentWebSocketHandler::handleMessage(const std::vector<char>& data)
|
|||
|
||||
if (tokens[1] == "jsdialog:")
|
||||
{
|
||||
terminateSave(tokens[0], "Unexpected jsdialog message: " +
|
||||
terminateSave("Unexpected jsdialog message: " +
|
||||
COOLProtocol::getAbbreviatedMessage(data));
|
||||
return;
|
||||
}
|
||||
|
@ -294,6 +302,7 @@ void BgSaveParentWebSocketHandler::handleMessage(const std::vector<char>& data)
|
|||
LOG_DBG("Failed to save, not synthesizing modified state");
|
||||
_document->disableBgSave("on failed save");
|
||||
}
|
||||
_saveCompleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,12 +310,22 @@ void BgSaveParentWebSocketHandler::handleMessage(const std::vector<char>& data)
|
|||
void BgSaveParentWebSocketHandler::onDisconnect()
|
||||
{
|
||||
LOG_TRC("Disconnected background web socket to child " << _childPid);
|
||||
|
||||
// reap and de-zombify children.
|
||||
int status = -1;
|
||||
if (waitpid(_childPid, &status, WUNTRACED | WNOHANG) > 0)
|
||||
{
|
||||
LOG_TRC("Child " << _childPid << " terminated with status " << status);
|
||||
if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGSEGV ||
|
||||
WTERMSIG(status) == SIGBUS ||
|
||||
WTERMSIG(status) == SIGABRT))
|
||||
reportFailedSave("crashed with status " + std::to_string(WTERMSIG(status)));
|
||||
}
|
||||
else
|
||||
LOG_TRC("Child disconnected but not terminated");
|
||||
LOG_WRN("Background save process disconnected but not terminated " << _childPid);
|
||||
|
||||
if (!_saveCompleted)
|
||||
reportFailedSave("terminated without saving");
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
|
@ -83,6 +83,7 @@ protected:
|
|||
class BgSaveParentWebSocketHandler final : public WebSocketHandler
|
||||
{
|
||||
pid_t _childPid;
|
||||
bool _saveCompleted;
|
||||
std::string _socketName;
|
||||
std::shared_ptr<Document> _document;
|
||||
std::shared_ptr<ChildSession> _session;
|
||||
|
@ -94,6 +95,7 @@ public:
|
|||
const std::shared_ptr<ChildSession> &session)
|
||||
: WebSocketHandler(/* isClient = */ false, /* isMasking */ false)
|
||||
, _childPid(childPid)
|
||||
, _saveCompleted(false)
|
||||
, _socketName(socketName)
|
||||
, _document(std::move(document))
|
||||
, _session(session)
|
||||
|
@ -109,6 +111,9 @@ protected:
|
|||
virtual void handleMessage(const std::vector<char>& data) override;
|
||||
virtual void onDisconnect() override;
|
||||
|
||||
// something weird happened, cleanup & notify of failure
|
||||
void terminateSave(const std::string &session, const std::string &reason);
|
||||
// something weird happened, cleanup & report save failure
|
||||
void terminateSave(const std::string &reason);
|
||||
|
||||
// let WSD know something went wrong during the save
|
||||
void reportFailedSave(const std::string &reason);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue