2
0
mirror of https://github.com/meganz/MEGAcmd synced 2025-08-22 09:57: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);
}
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

View File

@ -211,6 +211,7 @@ private:
public:
MegaCmdGlobalListener(MegaCmdLogger *logger, MegaCmdSandbox *sandboxCMD);
void onNodesUpdate(mega::MegaApi* api, mega::MegaNodeList *nodes);
void onUsersUpdate(mega::MegaApi* api, mega::MegaUserList *users);
void onAccountUpdate(mega::MegaApi *api);
@ -281,5 +282,20 @@ protected:
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
#endif // LISTENERS_H

View File

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

View File

@ -2935,23 +2935,9 @@ void MegaCmdExecuter::fetchNodes(MegaApi *api, int clientID)
#endif
}
void MegaCmdExecuter::actUponLogout(SynchronousRequestListener *srl, bool keptSession, int timeout)
void MegaCmdExecuter::actUponLogout(MegaApi& api, MegaError* e, bool keptSession)
{
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;
}
}
if (srl->getError()->getErrorCode() == MegaError::API_ESID || checkNoErrors(srl->getError(), "logout"))
if (e->getErrorCode() == MegaError::API_ESID || checkNoErrors(e, "logout"))
{
LOG_verbose << "actUponLogout logout ok";
cwd = UNDEF;
@ -2972,7 +2958,25 @@ void MegaCmdExecuter::actUponLogout(SynchronousRequestListener *srl, bool keptSe
clearGreetingStatusAllListener();
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)

View File

@ -144,9 +144,10 @@ public:
void changePassword(const char *newpassword, std::string pin2fa = "");
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);
int actUponLogin(mega::SynchronousRequestListener *srl, int timeout = -1);
void actUponLogout(mega::SynchronousRequestListener *srl, bool deletedSession, int timeout = 0);
int actUponCreateFolder(mega::SynchronousRequestListener *srl, int timeout = 0);
int actUponLogin(mega::SynchronousRequestListener *srl, int timeout = -1);
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 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);
void downloadNode(std::string source, std::string localPath, mega::MegaApi* api, mega::MegaNode *node, bool background, bool ignorequotawar, int clientID, std::shared_ptr<MegaCmdMultiTransferListener> listener);