I am trying to use the libnm library to call NetworkManager calls from one thread while another thread takes care of iterating the context and handling the callbacks of the asynchronous methods. Yet whatever I do, I cannot seem to shake these three critical glib warnings:
GLib-CRITICAL **: 15:55:38.490: g_main_context_push_thread_default: assertion 'acquired_context' failed
GLib-CRITICAL **: 15:55:38.490: g_main_context_pop_thread_default: assertion 'g_queue_peek_head (stack) == context' failed
libnm-CRITICAL **: 15:55:38.491: ((libnm/nm-client.c:5925)): assertion '<dropped>' failed
I have made a minimally reproducible example seen below
#include <thread>
#include <glib.h>
#include <gio/gio.h>
#include <iostream>
#include <NetworkManager.h>
class NetworkManager
{
public:
NetworkManager()
{
std::cout << "Network manager creation" << std::endl;
GError* error;
m_client = nm_client_new(nullptr, &error);
m_context = nm_client_get_main_context(m_client);
m_thread = std::thread([this]() {
g_main_context_push_thread_default(m_context);
while (true)
{
g_main_context_iteration(m_context, true);
}
g_main_context_pop_thread_default(m_context);
});
std::this_thread::sleep_for(std::chrono::seconds(1));
nm_client_reload_connections_async(m_client, nullptr, (GAsyncReadyCallback)callback, this);
}
~NetworkManager() {};
static void callback(GObject*, GAsyncResult*, gpointer data)
{
auto nm_ptr = static_cast<NetworkManager*>(data);
bool success = nm_client_reload_connections_finish(nm_ptr->m_client, nullptr, nullptr);
std::cout << success << std::endl;
}
std::thread m_thread;
GMainContext* m_context;
NMClient* m_client;
};
int main() {
NetworkManager nm{};
int i = 0;
while(true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << i++ << std::endl;
}
}
Have I misunderstood how the main context thread pushing and popping works? I have read the Main Context tutorial but I still do not completely understand how to correctly handle the main context from another thread.
worker_context = g_main_context_new ();. The first assertion basically says that the context you are trying to use is already owned somewhere else.