Is there a limit on the number of connections that can be opened?

145 views
Skip to first unread message

bservicer

unread,
Nov 20, 2020, 6:08:28 AM11/20/20
to libm...@googlegroups.com

Hello,

I am currently developing an equipment based on a Raspberry Pi 4 box that must be supervised by a separate controller interfaced in Modbus.

The supervisor is developed by a separate organization which initially started by opening and closing the connection on every query (say once per second).
We have faced a problem on such a framework in that every around 1000 queries (and related open/close activities) we receive a buffer overflow error on modbus_receive (). The threshold is not constant in time but is always in the range 1005÷1015 queries.

The buffer passed to the function is already dimensioned to MODBUS_TCP_MAX_ADU_LENGTH, and doubling its size does not change this behaviour. If the connection is kept open we have no problem in maintaining the system active for a long time.  Is this an expected behavior or can it be fixed someway?

If that matters, program is developed in C using Code:Blocks.

Communication via modbus is developed as a separate thread alogside this pseudocode (error checking removed for clarity):

void *modbusCbk (void *arg)
{
    // Declaration of local variables...

    //printf ("tread function entry point\n");
    thdStatus = THD_ACTIVE;

    // Inizialization of Modbus subsystem
    ctx   = modbus_new_tcp (NULL, port);
    query = malloc (MODBUS_TCP_MAX_ADU_LENGTH * 2);
    header_length = modbus_get_header_length (ctx);

//    modbus_set_debug (ctx, TRUE);

    // Allocating memory
    mb_mapping = modbus_mapping_new_start_address(
        0, 0,                                    // UT_BITS_ADDRESS, UT_BITS_NB,
        0, 0,                                    // UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,
        holdRegAdrs, holdRegNbr,        // UT_REGISTERS_ADDRESS, , UT_REGISTERS_NB_MAX
        inpRegAdrs, inpRegNbr            // UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB
    );

    s = modbus_tcp_listen (ctx, 2);

loopStart:
    modbus_tcp_accept (ctx, &s);        // Accept a connection

    cliConn = 1;            // Client connected flag

    while (TRUE) {
        do {
            if (thdStatus != THD_ACTIVE)
                goto loopEnd;
            rc = modbus_receive (ctx, query);
            /* Filtered queries return 0 */
        } while (rc == 0);

        /* The connection is not closed on errors which require on reply such as
           bad CRC in RTU. */
        if (rc == -1 && errno != EMBBADCRC) {
            /* Quit */
            //printf ("Bad CRC error detected\n");
            break;
        }

       // READ INPUT REGISTERS
        if (query[header_length] == 0x04) {
            rc = modbus_reply (ctx, query, rc, mb_mapping);
            if (rc == -1) {
                printf ("Error in modbus_reply detected (errno = %d)\n", errno);
                break;
            }

            // Build up response
            // .....
            memcpy (mb_mapping->tab_input_registers, &mbSts, sizeof (mbSts));
        }

        // WRITE MULTIPLE HOLDING REGISTERS
        else if (query[header_length] == 0x10) {
            rc = modbus_reply (ctx, query, rc, mb_mapping);
            if (rc == -1) {
                printf ("Error in modbus_reply detected (errno = %d)\n", errno);
                break;
            }

            // Reading parameters...
            // ...
        }

    }

    cliConn = 0;    // Client disconnected

    if (thdStatus < THD_CLOSING) goto loopStart;

loopEnd:
    if (s != -1) {
        close(s);
    }
    modbus_mapping_free (mb_mapping);
    free (query);
    modbus_close (ctx);
    modbus_free (ctx);

    thdStatus = THD_OFF;

    return NULL;
}


Thanks
Roberto

Richard Ash

unread,
Nov 24, 2020, 6:29:58 PM11/24/20
to bservicer, libm...@googlegroups.com
On Fri, 20 Nov 2020 12:08:26 +0100
bservicer <bser...@fastwebnet.it> wrote:

> Hello,
>
> I am currently developing an equipment based on a Raspberry Pi 4 box
> that must be supervised by a separate controller interfaced in Modbus.
>
> The supervisor is developed by a separate organization which
> initially started by opening and closing the connection on every
> query (say once per second).
> We have faced a problem on such a framework in that every around 1000
> queries (and related open/close activities) we receive a buffer
> overflow error on modbus_receive (). The threshold is not constant in
> time but is always in the range 1005÷1015 queries.

I suggest (based on the number a little less than 1024) that you are
leaking file descriptors (by not closing the connections correctly
somewhere), and so running out of file handles, leading to the
"overflow error".

Each process on Linux has 1024 file descriptors available to it (by
default), one is used each time a file or pseudo-file is opened, and
they are freed and re-used on orderly closure. Three are in use when
your program starts for standard in, standard out and standard error
(although you can close them).

> The buffer passed to the function is already dimensioned to
> MODBUS_TCP_MAX_ADU_LENGTH, and doubling its size does not change this
> behaviour. If the connection is kept open we have no problem in
> maintaining the system active for a long time.  Is this an expected
> behavior or can it be fixed someway?

The solution is to make sure that connections are closed (on both
sides) once not in use! But I can't advise on the detail of doing so,
as I have mostly used libmodbus with physical serial ports rather than
TCP (which you imply).

Richard

Roberto Bozzolo

unread,
Nov 25, 2020, 6:46:00 AM11/25/20
to libmodbus
Thanks Richard, I was supposing I was hitting some system limitations.
Unfortunately changing my loop to this schema doesn't help as I'm still getting the too many files open error in modbus_tcp_accept:

modbus_new_tcp 
modbus_mapping_new_start_address

Start of the loop:
s = modbus_tcp_listen 
modbus_tcp_accept (... , &s)
modbus_receive
(either receives a valid message or gets a disconnection error)
modbus_reply 
close (s)
End of the loop:

modbus_close 
modbus_free 

So the actual question becomes: How do I properly close a connection and free associated resources?

Richard Ash

unread,
Dec 3, 2020, 10:07:30 AM12/3/20
to libm...@googlegroups.com
> So the actual question becomes: How do I properly close a connection and free associated resources?
I would assume with modbus_close() https://libmodbus.org/docs/v3.1.6/modbus_close.html but I have not had cause to stress test like you are doing.

Richard

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "libmodbus".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse libmodbus+...@googlegroups.com.
Cette discussion peut être lue sur le Web à l'adresse https://groups.google.com/d/msgid/libmodbus/a2263117-5535-4000-a1ff-63984275b3dan%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages