Event loop hangup when using TimeoutSource and IdleSource



I am trying to create a pretty simple gtkmm application. The purpose of the application is to display the status of an attached device and to also send commands to the device to control it. The device is connected to the computer via a serial port and abstracted by a library API that I also wrote. My gtkmm application is designed to poll the device for various status via one function that gets called every 100 ms via a TimeoutSource.

code:

sigc::slot<bool> timerSlot = sigc::bind(sigc::mem_fun(*this, &Emsac::updateEMSStatus), true); sigc::connection conn = Glib::signal_timeout().connect(timerSlot, STATUS_UPDATE_RATE_MS, Glib::PRIORITY_HIGH_IDLE);

This function looks something like this:

bool Emsac::updateEMSStatus(bool meaningless)
{
	// This function gets called every 100 ms,
	// so every 10 counts is 1 s:
	static uint8_t count = 1;

	try {
		// Every 1 second:
		if (count % 10 == 0)
		{
			this->getPrimaryPackCurrent();
			this->getSecondaryPackCurrent();
		}

		// Every 2 seconds:
		if (count % 20 == 0)
		{
			...
		}

		...

	}
	catch (EMSNotInitialized &e) {
Logger::Instance().Warn("EMS not yet initialized, not updating EMS Status window data.");
	}

	++count;

	// Cause the timer to fire again:
	return true;
}

Each function, such as getPrimaryPackCurrent, sends a command to the device with a unique message ID. When the device replies, it has that same message ID attached and the library is setup to call a callback function with the requested data as function's parameter(s). The function would look like this:

void Emsac::getPrimaryPackCurrent() throw (EMSNotInitialized)
{
// Make sure that the EMS has been properly initialized before performing
	// this command:
	if (!ems_initialized())
		throw EMSNotInitialized(__FILE__, __LINE__);

	int ret = LIBEMSACI_SUCCESS;

ret = get_primary_pack_current(Emsac::getPrimaryPackCurrentCbWrapper, (void *)this, sizeof(Emsac));
}

The callback wrapper function looks like this:

void Emsac::getPrimaryPackCurrentCbWrapper(void *pObject, void *p_user, size_t len)
{
	assert(pObject);
	assert(p_user);

	Emsac *emsac = reinterpret_cast<Emsac *>(pObject);
	float current = *(static_cast<float *>(p_user));
Glib::signal_idle().connect(sigc::bind(sigc::mem_fun(*emsac, &Emsac::getPrimaryPackCurrentCb), current), Glib::PRIORITY_HIGH_IDLE);
}

And then the function that updates the GUI:

bool Emsac::getPrimaryPackCurrentCb(float current)
{
Logger::Instance().Info("Entering " + Helper::Instance ().charArrayToString(__FUNCTION__));

	try {
this->labelPPC->set_text(Glib::ustring::format(std::fixed, setprecision(4), current, " A"));
	}
	catch (Glib::ConvertError &e) {
		this->labelPPC->set_text(Glib::ustring("n/a"));
	}

	// Disconnect the idle handler from firing again:
	return false;
}

The weird part is that this "loop" of calling the updateEMSStatus() function via the TimeoutSource hangs randomly. It sometimes will hang after one cycle through (meaning through every status get request that fires in 1 second, 2 seconds, 5 seconds, etc)), and sometimes it'll do several cycles through with the timer returning hundreds of times. It doesn't seem to get stuck in any of my functions, it seems to be the Glib event loop that is getting stuck because my GUI becomes completely unresponsive. Any thoughts? Am I not using the Idlesource in a proper manner? Is this a resource leak somehow? How would I go about debugging where in the Glib event loop it might be hanging at?


Thanks,

Jim


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]