mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-07 14:12:43 -04:00
Solve race condition in JSON API restart
Improve atomic access to restbed service Protect JSON API restart against bursts Fix JSON API error condition enum registration Provide ostream helper for error_condition Provide optional forced thread cancel for debugging purpose, disabled by default at compile time define RS_THREAD_FORCE_STOP to enable it Avoid double fullstop in retroshare-gui json api apply button
This commit is contained in:
parent
7757c685c5
commit
039e8f653d
8 changed files with 236 additions and 72 deletions
|
@ -30,6 +30,7 @@
|
|||
#include <set>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
#include "pqi/p3cfgmgr.h"
|
||||
|
@ -40,6 +41,7 @@
|
|||
|
||||
namespace rb = restbed;
|
||||
|
||||
/** Interface to provide addotional resources to JsonApiServer */
|
||||
class JsonApiResourceProvider
|
||||
{
|
||||
public:
|
||||
|
@ -66,7 +68,7 @@ public:
|
|||
void fullstop() override { RsThread::fullstop(); }
|
||||
|
||||
/// @see RsJsonApi
|
||||
void restart() override;
|
||||
std::error_condition restart() override;
|
||||
|
||||
/// @see RsJsonApi
|
||||
void askForStop() override { RsThread::askForStop(); }
|
||||
|
@ -145,10 +147,6 @@ public:
|
|||
const std::function<bool(const std::string&, const std::string&)>&
|
||||
callback );
|
||||
|
||||
/// @see RsJsonApi
|
||||
const std::error_category& errorCategory() override
|
||||
{ return sErrorCategory; }
|
||||
|
||||
protected:
|
||||
/// @see RsThread
|
||||
void onStopRequested() override;
|
||||
|
@ -206,13 +204,33 @@ private:
|
|||
std::reference_wrapper<const JsonApiResourceProvider>,
|
||||
std::less<const JsonApiResourceProvider> > mResourceProviders;
|
||||
|
||||
/**
|
||||
* This pointer should be accessed via std::atomic_* operations, up until
|
||||
* now only very critical operations like reallocation, are done that way,
|
||||
* but this is not still 100% thread safe, but seems to handle all of the
|
||||
* test cases (no crash, no deadlock), once we switch to C++20 we shoud
|
||||
* change this into std::atomic<std::shared_ptr<restbed::Service>> which
|
||||
* will automatically handle atomic access properly all the times
|
||||
*/
|
||||
std::shared_ptr<restbed::Service> mService;
|
||||
/** Protect service only during very critical operation like resetting the
|
||||
* pointer, still not 100% thread safe, but hopefully we can avoid
|
||||
* crashes/freeze with this */
|
||||
RsMutex mServiceMutex;
|
||||
|
||||
uint16_t mListeningPort;
|
||||
std::string mBindingAddress;
|
||||
|
||||
/// @see unProtectedRestart()
|
||||
std::atomic<rstime_t> mRestartReqTS;
|
||||
|
||||
/// @see unProtectedRestart()
|
||||
constexpr static rstime_t RESTART_BURST_PROTECTION = 7;
|
||||
|
||||
/** It is very important to protect this method from being called in bursts,
|
||||
* because Restbed::Service::stop() together with
|
||||
* Restbed::Service::start(...), which are called internally, silently fails
|
||||
* if combined in bursts, probably because they have to deal with
|
||||
* listening/releasing TCP port.
|
||||
* @see JsonApiServer::restart() and @see JsonApiServer::JsonApiServer()
|
||||
* implementation to understand how correctly use this.
|
||||
*/
|
||||
void unProtectedRestart();
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue