2
0
mirror of https://github.com/meganz/MEGAcmd synced 2025-08-22 18:07:09 +00:00

Merge branch 'task/CMD-265_react_to_new_sdk_fatal_errors' into 'develop'

CMD-265. React to new EVENT_FATAL_ERROR apropiately

Closes CMD-265

See merge request apps/MEGAcmd!870
This commit is contained in:
Diego Ximenez 2025-03-18 01:16:37 +13:00
commit 511ecc03be
5 changed files with 167 additions and 27 deletions

View File

@ -1293,4 +1293,119 @@ bool ATransferListener::onTransferData(MegaApi *api, MegaTransfer *transfer, cha
return mMultiTransferListener->onTransferData(api, transfer, buffer, size); return mMultiTransferListener->onTransferData(api, transfer, buffer, size);
} }
std::string_view MegaCmdFatalErrorListener::getFatalErrorStr(int64_t fatalErrorType)
{
switch (fatalErrorType)
{
case MegaEvent::REASON_ERROR_UNKNOWN: return "REASON_ERROR_UNKNOWN";
case MegaEvent::REASON_ERROR_NO_ERROR: return "REASON_ERROR_NO_ERROR";
case MegaEvent::REASON_ERROR_FAILURE_UNSERIALIZE_NODE: return "REASON_ERROR_FAILURE_UNSERIALIZE_NODE";
case MegaEvent::REASON_ERROR_DB_IO_FAILURE: return "REASON_ERROR_DB_IO_FAILURE";
case MegaEvent::REASON_ERROR_DB_FULL: return "REASON_ERROR_DB_FULL";
case MegaEvent::REASON_ERROR_DB_INDEX_OVERFLOW: return "REASON_ERROR_DB_INDEX_OVERFLOW";
case MegaEvent::REASON_ERROR_NO_JSCD: return "REASON_ERROR_NO_JSCD";
case MegaEvent::REASON_ERROR_REGENERATE_JSCD: return "REASON_ERROR_REGENERATE_JSCD";
default: assert(false);
return "<unhandled fatal error>";
}
}
template<bool localLogout>
MegaRequestListener* MegaCmdFatalErrorListener::createLogoutListener(std::string_view msg)
{
return new MegaCmdListenerFuncExecuter(
[this, msg] (mega::MegaApi *api, mega::MegaRequest *request, mega::MegaError *e)
{
broadcastMessage(std::string(msg));
mCmdSandbox.cmdexecuter->actUponLogout(*api, e, localLogout);
}, true /* autoremove */
);
}
void MegaCmdFatalErrorListener::onEvent(mega::MegaApi *api, mega::MegaEvent *event)
{
assert(api); assert(event);
if (event->getType() != MegaEvent::EVENT_FATAL_ERROR)
{
return;
}
const int64_t fatalErrorType = event->getNumber();
LOG_err << "Received fatal error " << getFatalErrorStr(fatalErrorType) << " (type: " << fatalErrorType << ")";
switch (fatalErrorType)
{
case MegaEvent::REASON_ERROR_UNKNOWN:
{
broadcastMessage("An error is causing the communication with MEGA to fail. Your syncs and backups "
"are unable to update, and there may be further issues if you continue using MEGAcmd "
"without restarting. We strongly recommend immediately restarting the MEGAcmd server to "
"resolve this problem. If the issue persists, please contact support.");
break;
}
case MegaEvent::REASON_ERROR_NO_ERROR:
{
break;
}
case MegaEvent::REASON_ERROR_FAILURE_UNSERIALIZE_NODE:
{
broadcastMessage("A serious issue has been detected in MEGAcmd, or in the connection between "
"this device and MEGA. Delete your local \".megaCmd\" folder and reinstall the app "
"from https://mega.io/cmd, or contact support for further assistance.");
break;
}
case MegaEvent::REASON_ERROR_DB_IO_FAILURE:
{
std::string_view msg = "Critical system files which are required by MEGACmd are unable to be reached. "
"Please check permissions in the \".megaCmd\" folder, or try restarting the "
"MEGAcmd server. If the issue still persists, please contact support.";
api->localLogout(createLogoutListener<true>(msg));
break;
}
case MegaEvent::REASON_ERROR_DB_FULL:
{
std::string_view msg = "There's not enough space in your local storage to run MEGAcmd. Please make "
"more space available before running MEGAcmd.";
api->localLogout(createLogoutListener<true>(msg));
break;
}
case MegaEvent::REASON_ERROR_DB_INDEX_OVERFLOW:
{
std::string_view msg = "MEGAcmd has detected a critical internal error and needs to reload. "
"You've been logged out. If you experience this issue more than once, please contact support.";
// According to the Confluence documentation on fatal errors, this should be an account reload
// We'll do a logout instead to avoid problems with api folders
api->logout(false, createLogoutListener<false>(msg));
break;
}
case MegaEvent::REASON_ERROR_NO_JSCD:
{
broadcastMessage("MEGAcmd has detected an error in your sync configuration data. You need to manually "
"logout of MEGAcmd, and log back in, to resolve this issue. If the problem persists "
"afterwards, please contact support.");
break;
}
case MegaEvent::REASON_ERROR_REGENERATE_JSCD:
{
broadcastMessage("MEGAcmd has detected an error in your sync data. Please, reconfigure your syncs now. "
"If the issue persists afterwards, please contact support.");
break;
}
default:
{
LOG_err << "Unhandled fatal error type " << fatalErrorType;
assert(false);
break;
}
}
}
MegaCmdFatalErrorListener::MegaCmdFatalErrorListener(MegaCmdSandbox& cmdSandbox) :
mCmdSandbox(cmdSandbox)
{
}
} //end namespace } //end namespace

View File

@ -211,6 +211,7 @@ private:
public: public:
MegaCmdGlobalListener(MegaCmdLogger *logger, MegaCmdSandbox *sandboxCMD); MegaCmdGlobalListener(MegaCmdLogger *logger, MegaCmdSandbox *sandboxCMD);
void onNodesUpdate(mega::MegaApi* api, mega::MegaNodeList *nodes); void onNodesUpdate(mega::MegaApi* api, mega::MegaNodeList *nodes);
void onUsersUpdate(mega::MegaApi* api, mega::MegaUserList *users); void onUsersUpdate(mega::MegaApi* api, mega::MegaUserList *users);
void onAccountUpdate(mega::MegaApi *api); void onAccountUpdate(mega::MegaApi *api);
@ -281,5 +282,20 @@ protected:
mega::MegaTransferListener *listener; mega::MegaTransferListener *listener;
}; };
class MegaCmdFatalErrorListener : public mega::MegaGlobalListener
{
MegaCmdSandbox& mCmdSandbox;
static std::string_view getFatalErrorStr(int64_t fatalErrorType);
template<bool localLogout>
mega::MegaRequestListener* createLogoutListener(std::string_view msg);
void onEvent(mega::MegaApi *api, mega::MegaEvent *event) override;
public:
MegaCmdFatalErrorListener(MegaCmdSandbox& cmdSandbox);
};
} //end namespace } //end namespace
#endif // LISTENERS_H #endif // LISTENERS_H

View File

@ -5341,6 +5341,13 @@ int executeServer(int argc, char* argv[],
api->setLanguage(localecode.c_str()); api->setLanguage(localecode.c_str());
api->setLogJSONContent(logConfig.mJsonLogs); api->setLogJSONContent(logConfig.mJsonLogs);
LOG_debug << "Language set to: " << localecode;
sandboxCMD = new MegaCmdSandbox();
cmdexecuter = new MegaCmdExecuter(api, loggerCMD, sandboxCMD);
sandboxCMD->cmdexecuter = cmdexecuter;
auto cmdFatalErrorListener = std::make_unique<MegaCmdFatalErrorListener>(*sandboxCMD);
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
@ -5349,9 +5356,11 @@ int executeServer(int argc, char* argv[],
MegaApi *apiFolder = new MegaApi("BdARkQSQ", apiFolderStrUtf8.c_str(), userAgent); MegaApi *apiFolder = new MegaApi("BdARkQSQ", apiFolderStrUtf8.c_str(), userAgent);
apiFolder->setLanguage(localecode.c_str()); apiFolder->setLanguage(localecode.c_str());
apiFolders.push(apiFolder);
apiFolder->setLogLevel(MegaApi::LOG_LEVEL_MAX); apiFolder->setLogLevel(MegaApi::LOG_LEVEL_MAX);
apiFolder->setLogJSONContent(logConfig.mJsonLogs); apiFolder->setLogJSONContent(logConfig.mJsonLogs);
apiFolder->addGlobalListener(cmdFatalErrorListener.get());
apiFolders.push(apiFolder);
semaphoreapiFolders.release(); semaphoreapiFolders.release();
} }
@ -5360,20 +5369,15 @@ int executeServer(int argc, char* argv[],
semaphoreClients.release(); semaphoreClients.release();
} }
LOG_debug << "Language set to: " << localecode;
if (const char* fuseLogLevelStr = getenv("MEGACMD_FUSE_LOG_LEVEL"); fuseLogLevelStr) if (const char* fuseLogLevelStr = getenv("MEGACMD_FUSE_LOG_LEVEL"); fuseLogLevelStr)
{ {
setFuseLogLevel(*api, fuseLogLevelStr); setFuseLogLevel(*api, fuseLogLevelStr);
} }
sandboxCMD = new MegaCmdSandbox();
cmdexecuter = new MegaCmdExecuter(api, loggerCMD, sandboxCMD);
sandboxCMD->cmdexecuter = cmdexecuter;
megaCmdGlobalListener = new MegaCmdGlobalListener(loggerCMD, sandboxCMD); megaCmdGlobalListener = new MegaCmdGlobalListener(loggerCMD, sandboxCMD);
megaCmdMegaListener = new MegaCmdMegaListener(api, NULL, sandboxCMD); megaCmdMegaListener = new MegaCmdMegaListener(api, NULL, sandboxCMD);
api->addGlobalListener(megaCmdGlobalListener); api->addGlobalListener(megaCmdGlobalListener);
api->addGlobalListener(cmdFatalErrorListener.get());
api->addListener(megaCmdMegaListener); api->addListener(megaCmdMegaListener);
// set up the console // set up the console

View File

@ -2935,23 +2935,9 @@ void MegaCmdExecuter::fetchNodes(MegaApi *api, int clientID)
#endif #endif
} }
void MegaCmdExecuter::actUponLogout(SynchronousRequestListener *srl, bool keptSession, int timeout) void MegaCmdExecuter::actUponLogout(MegaApi& api, MegaError* e, bool keptSession)
{ {
if (!timeout) if (e->getErrorCode() == MegaError::API_ESID || checkNoErrors(e, "logout"))
{
srl->wait();
}
else
{
int trywaitout = srl->trywait(timeout);
if (trywaitout)
{
LOG_err << "Logout took too long, it may have failed. No further actions performed";
return;
}
}
if (srl->getError()->getErrorCode() == MegaError::API_ESID || checkNoErrors(srl->getError(), "logout"))
{ {
LOG_verbose << "actUponLogout logout ok"; LOG_verbose << "actUponLogout logout ok";
cwd = UNDEF; cwd = UNDEF;
@ -2972,7 +2958,25 @@ void MegaCmdExecuter::actUponLogout(SynchronousRequestListener *srl, bool keptSe
clearGreetingStatusAllListener(); clearGreetingStatusAllListener();
clearGreetingStatusFirstListener(); clearGreetingStatusFirstListener();
} }
updateprompt(api); updateprompt(&api);
}
void MegaCmdExecuter::actUponLogout(SynchronousRequestListener *srl, bool keptSession, int timeout)
{
if (!timeout)
{
srl->wait();
}
else
{
int trywaitout = srl->trywait(timeout);
if (trywaitout)
{
LOG_err << "Logout took too long, it may have failed. No further actions performed";
return;
}
}
actUponLogout(*api, srl->getError(), keptSession);
} }
int MegaCmdExecuter::actUponCreateFolder(SynchronousRequestListener *srl, int timeout) int MegaCmdExecuter::actUponCreateFolder(SynchronousRequestListener *srl, int timeout)

View File

@ -145,7 +145,8 @@ public:
void actUponGetExtendedAccountDetails(std::unique_ptr<mega::MegaAccountDetails> storageDetails, std::unique_ptr<mega::MegaAccountDetails> extAccountDetails); void actUponGetExtendedAccountDetails(std::unique_ptr<mega::MegaAccountDetails> storageDetails, std::unique_ptr<mega::MegaAccountDetails> extAccountDetails);
bool actUponFetchNodes(mega::MegaApi * api, mega::SynchronousRequestListener *srl, int timeout = -1); bool actUponFetchNodes(mega::MegaApi * api, mega::SynchronousRequestListener *srl, int timeout = -1);
int actUponLogin(mega::SynchronousRequestListener *srl, int timeout = -1); int actUponLogin(mega::SynchronousRequestListener *srl, int timeout = -1);
void actUponLogout(mega::SynchronousRequestListener *srl, bool deletedSession, int timeout = 0); void actUponLogout(mega::MegaApi& api, mega::MegaError* e, bool keptSession);
void actUponLogout(mega::SynchronousRequestListener *srl, bool keptSession, int timeout = 0);
int actUponCreateFolder(mega::SynchronousRequestListener *srl, int timeout = 0); int actUponCreateFolder(mega::SynchronousRequestListener *srl, int timeout = 0);
int deleteNode(const std::unique_ptr<mega::MegaNode>& nodeToDelete, mega::MegaApi* api, int recursive, int force = 0); int deleteNode(const std::unique_ptr<mega::MegaNode>& nodeToDelete, mega::MegaApi* api, int recursive, int force = 0);
int deleteNodeVersions(const std::unique_ptr<mega::MegaNode>& nodeToDelete, mega::MegaApi* api, int force = 0); int deleteNodeVersions(const std::unique_ptr<mega::MegaNode>& nodeToDelete, mega::MegaApi* api, int force = 0);