Fixes instances with infinite duration (#7547)

* Fixes #6230 and fixes #7472.
* Resolves an issue where instances that have infinite TimeLimit or IdleTimeOut would instantly become destroyed.
* Fixes an issue where do_final_instance() could end up on an invalid iterator value resulting in memleaks/crashes on map server closure.
* Add missing constructor parameters.
Thanks to @secretdataz, @Lemongrass3110, and @mazvi!
This commit is contained in:
Aleos
2023-01-11 14:25:11 -05:00
committed by GitHub
parent 14cb61d598
commit 3464292a31
2 changed files with 27 additions and 10 deletions

View File

@@ -93,13 +93,15 @@ uint64 InstanceDatabase::parseBodyNode(const ryml::NodeRef& node) {
if (!this->asInt64(node, "TimeLimit", limit))
return 0;
if (limit == 0) // Infinite duration
limit = INT64_MAX;
instance->limit = limit;
// Infinite duration
instance->infinite_limit = (limit == 0);
} else {
if (!exists)
if (!exists) {
instance->limit = 3600;
instance->infinite_limit = false;
}
}
if (this->nodeExists(node, "IdleTimeOut")) {
@@ -108,13 +110,15 @@ uint64 InstanceDatabase::parseBodyNode(const ryml::NodeRef& node) {
if (!this->asInt64(node, "IdleTimeOut", idle))
return 0;
if (idle == 0) // Infinite duration
idle = INT64_MAX;
instance->timeout = idle;
// Infinite duration
instance->infinite_timeout = (idle == 0);
} else {
if (!exists)
if (!exists) {
instance->timeout = 300;
instance->infinite_timeout = false;
}
}
if (this->nodeExists(node, "NoNpc")) {
@@ -404,6 +408,10 @@ bool instance_startkeeptimer(std::shared_ptr<s_instance_data> idata, int instanc
if (!db)
return false;
// Infinite duration instance
if (db->infinite_limit)
return true;
// Add timer
idata->keep_limit = time(nullptr) + db->limit;
idata->keep_timer = add_timer(gettick() + db->limit * 1000, instance_delete_timer, instance_id, 0);
@@ -451,6 +459,10 @@ bool instance_startidletimer(std::shared_ptr<s_instance_data> idata, int instanc
if (!db)
return false;
// Infinite idle duration instance
if (db->infinite_timeout)
return true;
// Add the timer
idata->idle_limit = time(nullptr) + db->timeout;
idata->idle_timer = add_timer(gettick() + db->timeout * 1000, instance_delete_timer, instance_id, 0);
@@ -1294,6 +1306,7 @@ void do_init_instance(void) {
* Finalizes the instances and instance database
*/
void do_final_instance(void) {
for (const auto &it : instances)
instance_destroy(it.first);
// Since instance_destroy() modifies the unordered_map, make sure iteration always restarts.
for (auto it = instances.begin(); it != instances.end(); it = instances.begin())
instance_destroy(it->first);
}