Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/api/Logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ namespace MAT_NS_BEGIN

Logger::~Logger() noexcept
{
LOG_TRACE("%p: Destroyed", this);
// Intentionally empty — logging here triggers a static-destruction-order
// crash on iOS simulator (recursive_mutex used after teardown).
}

ISemanticContext* Logger::GetSemanticContext() const
Expand Down
9 changes: 8 additions & 1 deletion lib/http/HttpClientManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,15 @@ namespace MAT_NS_BEGIN {
void HttpClientManager::cancelAllRequests()
{
cancelAllRequestsAsync();
while (!m_httpCallbacks.empty())
while (true)
{
{
LOCKGUARD(m_httpCallbacksMtx);
if (m_httpCallbacks.empty())
break;
}
std::this_thread::yield();
}
Comment thread
bmehta001 marked this conversation as resolved.
}

// start async cancellation
Expand Down
24 changes: 6 additions & 18 deletions lib/http/HttpClient_Apple.mm
Original file line number Diff line number Diff line change
Expand Up @@ -132,23 +132,6 @@ void HandleResponse(NSData* data, NSURLResponse* response, NSError* error)
void Cancel()
{
[m_dataTask cancel];
[session getTasksWithCompletionHandler:^(NSArray* dataTasks, NSArray* uploadTasks, NSArray* downloadTasks)
{
for (NSURLSessionTask* _task in dataTasks)
{
[_task cancel];
}

for (NSURLSessionTask* _task in downloadTasks)
{
[_task cancel];
}

for (NSURLSessionTask* _task in uploadTasks)
{
[_task cancel];
}
}];
}

private:
Expand Down Expand Up @@ -214,8 +197,13 @@ void Cancel()
for (const auto &id : ids)
CancelRequestAsync(id);

while (!m_requests.empty())
while (true)
{
{
std::lock_guard<std::mutex> lock(m_requestsMtx);
if (m_requests.empty())
break;
}
PAL::sleep(100);
std::this_thread::yield();
}
Expand Down
4 changes: 0 additions & 4 deletions lib/http/HttpResponseDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,11 @@ namespace MAT_NS_BEGIN {
break;

case HttpResult_Aborted:
ctx->httpResponse = nullptr;
outcome = Abort;
break;

case HttpResult_LocalFailure:
case HttpResult_NetworkFailure:
ctx->httpResponse = nullptr;
outcome = RetryNetwork;
break;
}
Expand Down Expand Up @@ -129,7 +127,6 @@ namespace MAT_NS_BEGIN {
evt.param1 = 0; // response.GetStatusCode();
DispatchEvent(evt);
}
ctx->httpResponse = nullptr;
// eventsRejected(ctx); // FIXME: [MG] - investigate why ctx gets corrupt after eventsRejected
requestAborted(ctx);
break;
Expand Down Expand Up @@ -253,4 +250,3 @@ namespace MAT_NS_BEGIN {
}

} MAT_NS_END

65 changes: 49 additions & 16 deletions lib/pal/WorkerThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "pal/WorkerThread.hpp"
#include "pal/PAL.hpp"

#include <system_error>

#if defined(MATSDK_PAL_CPP11) || defined(MATSDK_PAL_WIN32)

/* Maximum scheduler interval for SDK is 1 hour required for clamping in case of monotonic clock drift */
Expand Down Expand Up @@ -35,7 +37,7 @@ namespace PAL_NS_BEGIN {
std::list<MAT::Task*> m_timerQueue;
Event m_event;
MAT::Task* m_itemInProgress;
int count = 0;
bool m_shuttingDown = false;

public:

Expand All @@ -53,32 +55,65 @@ namespace PAL_NS_BEGIN {

void Join() final
{
auto item = new WorkerThreadShutdownItem();
Queue(item);
std::thread::id this_id = std::this_thread::get_id();
bool joined = false;
{
LOCKGUARD(m_lock);
if (!m_shuttingDown) {
m_shuttingDown = true;
m_queue.push_back(new WorkerThreadShutdownItem());
m_event.post();
}
}
try {
if (m_hThread.joinable() && (m_hThread.get_id() != this_id))
if (!m_hThread.joinable()) {
return;
}
if (m_hThread.get_id() != this_id) {
m_hThread.join();
else
joined = true;
} else {
m_hThread.detach();
}
}
catch (const std::system_error& e) {
LOG_ERROR("Thread join/detach failed: [%d] %s", e.code().value(), e.what());
}
catch (const std::exception& e) {
LOG_ERROR("Thread join/detach failed: %s", e.what());
}
catch (...) {};

// TODO: [MG] - investigate if we ever drop work items on shutdown.
if (!m_queue.empty())
{
LOG_WARN("m_queue is not empty!");
// Log pending work in both paths so operators can see if
// shutdown is dropping tasks.
LOCKGUARD(m_lock);
if (!m_queue.empty()) {
LOG_WARN("Shutdown with %zu queued task(s) pending", m_queue.size());
}
if (!m_timerQueue.empty())
{
LOG_WARN("m_timerQueue is not empty!");
if (!m_timerQueue.empty()) {
LOG_WARN("Shutdown with %zu timer(s) pending", m_timerQueue.size());
}

// Clean up any tasks remaining in the queues after shutdown.
// Only safe after join() — the thread has fully exited.
// After detach(), the thread still needs the shutdown item
// and may still be accessing the queues.
if (joined) {
for (auto task : m_queue) { delete task; }
m_queue.clear();
for (auto task : m_timerQueue) { delete task; }
Comment thread
bmehta001 marked this conversation as resolved.
m_timerQueue.clear();
}
}

void Queue(MAT::Task* item) final
{
LOG_INFO("queue item=%p", &item);
LOG_INFO("queue item=%p", static_cast<void*>(item));
LOCKGUARD(m_lock);
if (m_shuttingDown) {
LOG_WARN("Dropping queued task %p during shutdown", static_cast<void*>(item));
delete item;
return;
Comment thread
bmehta001 marked this conversation as resolved.
}
if (item->Type == MAT::Task::TimedCall) {
auto it = m_timerQueue.begin();
while (it != m_timerQueue.end() && (*it)->TargetTime < item->TargetTime) {
Expand All @@ -89,7 +124,6 @@ namespace PAL_NS_BEGIN {
else {
m_queue.push_back(item);
}
count++;
m_event.post();
}

Expand Down Expand Up @@ -261,4 +295,3 @@ namespace PAL_NS_BEGIN {
} PAL_NS_END

#endif

Loading
Loading