stephane / libmodbus

A Modbus library for Linux, Mac OS, FreeBSD and Windows
http://libmodbus.org
GNU Lesser General Public License v2.1
3.47k stars 1.75k forks source link

Calling frequently linux function write() to log to file causes libmodbus timeout for modbus_read_registers() #272

Closed killdaclick closed 9 years ago

killdaclick commented 9 years ago

Consider following code:

int ModbusDevice::modbusReceiveData( void )
{
    if( mb == nullptr )
        return -1;

    int regCnt = 0;
    for( ModbusResourceObjectList::iterator obj = mbMeasSyncDataSrc.resObjList.begin();
         obj != mbMeasSyncDataSrc.resObjList.end(); ++obj )
    {
        uint16_t reg[obj->regSize];
        int ret = modbus_read_registers( mb, obj->mbPtr, obj->regSize, reg );

        if( ret != obj->regSize || ret == -1 )
        {
            Kernel::Instance().message("<MB DEVICE: '%s'> Error reading measurement '%s' at register addres %d.\n\tError: %s\n",
                Kernel::MSG_TYPE::ERROR, Kernel::MSG_LEVEL::DEFAULT, mbDevName.c_str(), obj->ref.c_str(), obj->mbPtr, modbus_strerror(errno) );
            continue;
        }

        obj->mbVal = 0;
        for( int r = 0; r < obj->regSize; r++ )
            obj->mbVal |= reg[r]<<(r*16);

        Kernel::Instance().message("<MB DEVICE: '%s'> Successfully read measurement '%s' at register addres %d = %d.\n",
            Kernel::MSG_TYPE::DATA, Kernel::MSG_LEVEL::VERBOSE /*| Kernel::MSG_LEVEL::DONT_LOG_TO_FILE*/, mbDevName.c_str(),
            obj->ref.c_str(), obj->mbPtr, obj->mbVal );
        regCnt += obj->regSize;
    }

    return regCnt;
}

as you can see flag Kernel::MSG_LEVEL::DONT_LOG_TO_FILE is comment out in that example and everything is working fine. When we uncomment the flag method Kernel::message() logs everything to opened file using linux write() function, which causes function modbus_read_registers() to timeout always even if timeout are set to high values like 10 seconds.

Again commenting out write() or uncommenting Kernel::MSG_LEVEL::DONT_LOG_TO_FILE make libmodbus responsive again.

As I understand libmodbus uses write() to send data (??) so I assume that write() function does not finish writing to file descriptor and modbus_read_registers() is timedout?

stephane commented 9 years ago

If you write debug messages on the serial bus whereas you have Modbus devices connected on this bus, I'm not surprised you have communication issues!

PS: write() function has finished but your messages send garbage on the bus and it disturbs other devices which certainly sends unexpected data (that why reading fails). You can enable the debug mode to see that.