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.