Overview
Features
Download
Documentation
Community
Add-Ons & Services

Problems with Notifications

Please post support and help requests here.

Problems with Notifications

Postby tmiesch » 31 Dec 2009, 14:20

I am using the poco library for my SmallMGC application, which will be in the future a open source softswitch.
In the past I have used version 1.3.3 and now I have updated to 1.36 because I also wanted to use the data library with SQLite.
I am using Linux and also static linked libraries.

But now I have a different behaviour of previous working parts.
One thing is the stability of the application after reboots sometimes I encounter exceptions.
A trace stack is below:
Code: Select all
15 __cxa_throw()  0xb7e73e5d   
14 Poco::MutexImpl::lockImpl() Mutex_POSIX.h:82 0x08053e5b   
13 Poco::FastMutex::lock() Mutex.h:205 0x08053eaa   
12 ScopedLock() ScopedLock.h:59 0x08053ecc   
11 Poco::AtomicCounter::operator--() AtomicCounter.h:292 0x0805403b   
10 Poco::RefCountedObject::release() RefCountedObject.h:102 0x0805407d   
9 ~AutoPtr() AutoPtr.h:112 0x08056ff9   
8 Poco::NotificationQueue::dequeueOne() NotificationQueue.cpp:210 0x082ca35c   
7 Poco::NotificationQueue::waitDequeueNotification() NotificationQueue.cpp:106 0x082cade6   
6 SUB_H248_GatewayControl_Task::runTask() sub_h248_gatewaycontrol.cpp:61 0x080e81a8   


There is a mutex which can't be locked so that is an indication for me that the pointer is already released.
But in my application until now I haven't used AutoPtr but release the pointer myself after it was processed.
Processing the pointer means this is done after the waitDequeueNotification has returned.

Normally I have a receive thread which receives data from the network then this data is passed through Notifications to a message parser.
There the message parser creates different messages which are derived of the Notification class and send further to another thread through a Notification Queue.
One type of message I process and send it even further to another thread.

In the previous poco version this worked quite good, now with the 1.3.6 version there are sometimes exception.

At the moment my understanding is that this problem occurs because of the change from normal pointer to AutoPtr in the Notification.
It seems that a pointer is already released, in my code I release the Notifications only after they are processed so I don't understand why the Notification in that part should be released.

One point which I consider a problem is that I don't use an AutoPtr even with the received Notification which wasn't necessary in the previous Poco version.
I tried to implement this according to some examples, but then encountered another problem that with an AutoPtr polymorphisms is not possible anymore.

So how should I implement the following:

e.g
Code: Select all
class Command : public Notification
{
public:
    Command{};
    process();
}

class DerivedCommand : public Command
{
public:
    DerivedCommand();
    process();
}

class DerivedCommand1 : public Command
{
public:
    DerivedCommand1();
    process();
}
....
AutoPtr<Notification> pNf(m_queue.waitDequeueNotification());
AutoPtr<Command> message = pNf.cast<Command>();
message->process();


As I understand I could do the cast for every message type that I expect. But that is not what I want I would prefer to use polymorphism.
Is there another explanation for the not to be able to lock the mutex?

Thanks
Thomas
tmiesch
 
Posts: 7
Joined: 31 Dec 2009, 13:28

Re: Problems with Notifications

Postby guenter » 04 Jan 2010, 16:30

Looks like the reference counting in the Notification objects gets messed up for some reason. How does the code look where you enqueue your notification objects?

Regarding AutoPtr and polymorphism: If Command::process() is virtual, then you should be able to call it through an AutoPtr and the correct method should be called, depending on the actual class.

Also, you have rebuilt your entire application after upgrading POCO, haven't you?
guenter
 
Posts: 1154
Joined: 11 Jul 2006, 16:27
Location: Austria

Re: Problems with Notifications

Postby tmiesch » 04 Jan 2010, 21:05

Yes Command Process is virtual otherwise my code wouldn't work. So that should be ok.
To make sure that I have rebuilt my application, I have it done again and seen the same error, so that is not the cause of the problem

Now I put some code from my application

Dequeue of the Message?
Code: Select all
   H248STACK_Commands* receivedMessage= 0;
  receivedMessage = (H248STACK_Commands*)m_gateQueue.waitDequeueNotification(); // wait max 1s for the next message
  Application::instance().logger().error("Number of Messages in Reading GatewayQueue: " + NumberFormatter::format(m_gateQueue.size()));
  if (receivedMessage != 0)
  {
     Application::instance().logger().error("Packet Received.. " /*+ DateTimeFormatter::format(app.uptime())*/);
     receivedMessage->process(m_gatewayHandler);
     delete receivedMessage;
  }


Enqueue of the Message
Code: Select all
Poco::UInt32 ret = parse248((char*)message.c_str());
if (ret == 0)
{
  H248STACK_Commands* command = m_parser->getCommand();
  if (command != 0)
  {
    if (command->isForCallControl())
    {
      m_callQueue.enqueueNotification(command);
      Application::instance().logger().debug("Number of Messages in CallQueue: " + NumberFormatter::format(m_callQueue.size()));
    }
    else
    {
       m_gateQueue.enqueueNotification(command);
      Application::instance().logger().debug("Number of Messages in GateQueueA: " + NumberFormatter::format(m_gateQueue.size()));
    }
  }

}
else
{
    H248STACK_Commands* command = m_parser->getCommand();
    if (command != 0)
    {
      m_gateQueue.enqueueNotification(command);
      Application::instance().logger().debug("Number of Messages in GateQueueB: " + NumberFormatter::format(m_gateQueue.size()));
    }
    else
    {
      //printf("message %s", message.c_str());
    }
}


What I have added also is the access to a SQLite database and I am wondering if I have a problem there with the transaction times. Because what I see if there is a crash the queue size increases to about 13/14 messages and during the work to reduce the number the crash happens.
If there is no crash then I don't see any build up of the queue size.

I would consider to use the PRAGMA synchronous = 0 to look if that improves the situation, but until now I wasn't able to prepare the right statement.
tmiesch
 
Posts: 7
Joined: 31 Dec 2009, 13:28

Re: Problems with Notifications

Postby guenter » 04 Jan 2010, 23:59

A potential problem I see in your code is that you use delete to destroy the notification object. You should never do that -- generally you should never delete a reference counted object. Always use release(). This will take care of decrementing the reference count and deleting the object when the refcount becomes zero.
So, instead of
Code: Select all
delete receivedMessage;
do a
Code: Select all
receivedMessage->release();

Or even better, use Poco::AutoPtr. This will also make your code exception safe (the notification object won't leak if process() throws an exception, for example).

Regarding SQLite performance, you can do the following:
Code: Select all
Poco::Data::Session session("SQLite", "mydb.dat");
session.setProperty("transactionMode", std::string("IMMEDIATE"));
session << "PRAGMA synchronous = OFF", now;
session << "PRAGMA count_changes = OFF", now;
session << "PRAGMA read_uncommitted = ON", now;
guenter
 
Posts: 1154
Joined: 11 Jul 2006, 16:27
Location: Austria

Re: Problems with Notifications

Postby tmiesch » 05 Jan 2010, 21:07

Hi

I have implemented the SQLite statements and also changed the release of the Notifications as you have suggested.
But there is still a crash.
So I have to implement the Autoptr, but there I had Problems that polymorphism didn't worked.

Could you assist me and show how you would implement this part with an Autoptr?
Code: Select all
   H248STACK_Commands* receivedMessage= 0;
  receivedMessage = (H248STACK_Commands*)m_gateQueue.waitDequeueNotification(); // wait max 1s for the next message
  Application::instance().logger().error("Number of Messages in Reading GatewayQueue: " + NumberFormatter::format(m_gateQueue.size()));
  if (receivedMessage != 0)
  {
     Application::instance().logger().error("Packet Received.. " /*+ DateTimeFormatter::format(app.uptime())*/);
     receivedMessage->process(m_gatewayHandler);
     delete receivedMessage;
  }


Thanks for your support
Thomas
tmiesch
 
Posts: 7
Joined: 31 Dec 2009, 13:28

Re: Problems with Notifications

Postby guenter » 07 Jan 2010, 18:17

Here's some code that I'm using in a project that does a similar thing as your code:

Poco::AutoPtr<Poco::Notification> pNf = _actionQueue.waitDequeueNotification();
while (pNf)
{
Poco::AutoPtr<ActionNotification> pActionNf = pNf.cast<ActionNotification>();
if (pActionNf)
{
try
{
pActionNf->execute();
}
catch (Poco::Exception& exc)
{
_logger.error("Caught exception while processing notification: " + exc.displayText());
}
}
else if (pNf.cast<StopNotification>())
{
break;
}
pNf = _actionQueue.waitDequeueNotification();
}
guenter
 
Posts: 1154
Joined: 11 Jul 2006, 16:27
Location: Austria

Re: Problems with Notifications

Postby tmiesch » 11 Jan 2010, 20:36

Hi Guenter

I wanted to say thank you for your support.
I have changed my code to the examples provided by you and extended some other Pointers to AutoPtr and now the stability problem is solved.
Even the polyphorism is working.

Regards
Thomas
tmiesch
 
Posts: 7
Joined: 31 Dec 2009, 13:28


Return to Support

Who is online

Users browsing this forum: guenter and 2 guests