🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
5 messages
5 total messages Started by Drew Thu, 12 Aug 2004 15:45
'Out of memory' exception for a IdTCPServer
#5494
Author: Drew
Date: Thu, 12 Aug 2004 15:45
11 lines
1171 bytes
Can anyone tell me what an 'Out of memory' exception for a IdTCPServer
means?  The system is not low on memory, and will run for serveral hours
before this problem occurs.

Is there anything that I can do once ths has occurred - for instance, would
simply reconnecting the TCP connection be OK,or is this a more terminal
problem?

Thanks

Andrew
Re: 'Out of memory' exception for a IdTCPServer
#5496
Author: Remy Lebeau (TeamB)
Date: Thu, 12 Aug 2004 17:01
25 lines
1719 bytes
"Drew" <aemsley@brightwell.org.uk> wrote in message
news:411b903e@newsgroups.borland.com...

> Can anyone tell me what an 'Out of memory' exception
> for a IdTCPServer means?

Exactly what it says - it tried to allocate a piece of memory and could not
because the system did not have available memory for it.

> The system is not low on memory

There are many different types of memory and resources available for
allocation.  Any of them could be low.  And such an error is not specific to
Indy anyway, it is from the VCL itself.

> Is there anything that I can do once ths has occurred - for instance,
would
> simply reconnecting the TCP connection be OK

It depends on what exactly is failing to begin with.  Please provide more
details.  Where does the exception occur?  Under what circumstances?


Gambit
Re: 'Out of memory' exception for a IdTCPServer
#5497
Author: Drew
Date: Thu, 12 Aug 2004 21:21
206 lines
7923 bytes
The situation is as follows:

There are two applications (currently running on the same PC).  One
application sends values across a TCP link to the other application that
writes the values into the database.  They use a IdTCPClient/IdTCPServer
pair to form the TCP link.

On the server side, the following code is used to set up the IdTCPServer:

    RtrServer->OnDisconnect = RtrServerDisconnect;
    RtrServer->OnException  = RtrServerException;
    RtrServer->OnListenException = RtrServerListenException;
    RtrServer->Active = true;

    RtrServer->CommandHandlersEnabled = true;

    RtrServer->CommandHandlers->Add();
    RtrServer->CommandHandlers->Items[0]->Command = readRtrParams;
    RtrServer->CommandHandlers->Items[0]->OnCommand =
RtrServerReadRtrParams;

    RtrServer->CommandHandlers->Add();
    RtrServer->CommandHandlers->Items[1]->Command = read10Hilltops;
    RtrServer->CommandHandlers->Items[1]->OnCommand =
RtrServerReadMultipleHilltops;

    RtrServer->CommandHandlers->Add();
    RtrServer->CommandHandlers->Items[2]->Command = updateHilltopInfo;
    RtrServer->CommandHandlers->Items[2]->OnCommand =
RtrServerUpdateHilltops;

The exception handlers are as follows:

//--------------------------------------------------------------------------
-
void __fastcall RTRSvrThread::RtrServerDisconnect(TIdPeerThread *AThread)
{
    Log(0, "Rtr Server disconnected");
}
//--------------------------------------------------------------------------
-
void __fastcall RTRSvrThread::RtrServerException(TIdPeerThread *AThread,
Exception *e)
{
    sprintf(msg, "Rtr Server exception: %s", e->Message);
    Log(0, msg);
}
//--------------------------------------------------------------------------
-
void __fastcall RTRSvrThread::RtrServerListenException(TIdListenerThread
*Athread, Exception *e)
{
    Log(0, "Rtr Server listen exception");
}

The error log shows the following:

    19:59:43.56: Rtr Server exception: Out of memory
    19:59:43.56: Rtr server disconnected

The client has just sent a message of type 'updateHilltopInfo', which will
trigger the command handler 'RtrServerUpdateHilltops'.  The code on the
client side to send the message across the TCP link is:

  // Send the data obtained from the hilltop back to DBM to update the
database

  AnsiString msgType = updateHilltopInfo;

  Log(2, "Sending updateHilltopInfo message to DBM");

 if (DbmClient->Connected())
 {
       try
       {
               DbmClient->WriteLn(msgType);

               try
              {
                      msgType = DbmClient->ReadLn();

                      if (msgType == ACK)
                     {
                                Log(2, "Read ACK from DBM");
                               char* sendBuffer;

                               sendBuffer = new char[sizeof(SiteData_t)];

                               memcpy(sendBuffer, site, sizeof(SiteData_t));

                               Log(2, "Sending info buffer to DBM");
                               DbmClient->WriteBuffer(sendBuffer,
sizeof(SiteData_t));

                               delete[] sendBuffer;

                               try
                               {
                                       msgType = DbmClient->ReadLn();

                                       if (msgType == ACK)
                                       {
                                               Log(2, "Read ACK again from
DBM");
                                               {
                                                     sprintf(msg, "About to
delete site ID %d", site->siteID);
                                                     Log(2, msg);
                                               }
                                               if (site)
                                               {
                                                   delete site;
                                               }
                                               DecSiteCount();
                                        }
                                        msgSent = true;

                               }
                               catch (Exception &e)
                               {
                                      {
                                             sprintf(msg, "Read of second
ACK failed: exception = %s", e.Message);
                                              Log(0, msg);
                                       }
                               }
                     }
                     else
                     {
                             {
                                    sprintf(msg, "Read non-ACK reply from
DBM - msg = %s", msgType);
                                    Log(0, msg);
                             }
                    }
             }
             catch (Exception &e)
             {
                    Log(0, "Read of ACK from DBM failed");
                   {
                           sprintf(msg, "Exception generated = %s",
e.Message);
                           Log(0, msg);
                   }
             }
      }
      catch (Exception &e)
     {
            {
                  sprintf(msg, "Write of updateHilltopInfo message to DBM
failed: exception = %s", e.Message);
                  Log(0, msg);
            }
           msgSent = true;
    }

On the client side, the error log shows:

    19:59:43.56: Sending updateHilltopInfo message to DBM
    19:59:43.56: Read of ACK from DBM failed
    19:59:43.56: Exception gnerated = Connection Closed Gracefully.


This occrs after the system has been running for several hours (around 6 on
the last attempt).

Other applications on the same machine are using a similar mechanism to send
data to the server task, and these continue unaffected.

Can you see anything that I'm doing wrong?

Thanks

Andrew

"Remy Lebeau (TeamB)" <gambit47.no.spam@no.spam.yahoo.com> wrote in message
news:411ba247$1@newsgroups.borland.com...
>
> "Drew" <aemsley@brightwell.org.uk> wrote in message
> news:411b903e@newsgroups.borland.com...
>
> > Can anyone tell me what an 'Out of memory' exception
> > for a IdTCPServer means?
>
> Exactly what it says - it tried to allocate a piece of memory and could
not
> because the system did not have available memory for it.
>
> > The system is not low on memory
>
> There are many different types of memory and resources available for
> allocation.  Any of them could be low.  And such an error is not specific
to
> Indy anyway, it is from the VCL itself.
>
> > Is there anything that I can do once ths has occurred - for instance,
> would
> > simply reconnecting the TCP connection be OK
>
> It depends on what exactly is failing to begin with.  Please provide more
> details.  Where does the exception occur?  Under what circumstances?
>
>
> Gambit
>
>
Re: 'Out of memory' exception for a IdTCPServer
#5498
Author: Remy Lebeau (TeamB)
Date: Thu, 12 Aug 2004 21:38
67 lines
3081 bytes
"Drew" <aemsley@brightwell.org.uk> wrote in message
news:411bdf12$1@newsgroups.borland.com...

>     RtrServer->Active = true;
>
>     RtrServer->CommandHandlersEnabled = true;

You should set up the command handlers before you activate the server, not
afterwards.

>     RtrServer->CommandHandlers->Add();
>     RtrServer->CommandHandlers->Items[0]->Command = readRtrParams;
>     RtrServer->CommandHandlers->Items[0]->OnCommand =
> RtrServerReadRtrParams;

You should use the return value of Add() instead of indexing the Items[]
collection over and over:

    TIdCommandHandler *Handler = RtrServer->CommandHandlers->Add();
    Handler->Command = readRtrParams;
    Handler->->OnCommand = RtrServerReadRtrParams;

> void __fastcall RTRSvrThread::RtrServerDisconnect(TIdPeerThread *AThread)
> {
>     Log(0, "Rtr Server disconnected");
> }

What exactly does Log() do?  Is its code thread-safe?

> The error log shows the following:
>
>     19:59:43.56: Rtr Server exception: Out of memory
>     19:59:43.56: Rtr server disconnected

That suggests that one of your command handlers is probably where the
exception is being thrown.  Can you please show the actual handler code?

>                                char* sendBuffer;
>
>                                sendBuffer = new char[sizeof(SiteData_t)];
>
>                                memcpy(sendBuffer, site,
sizeof(SiteData_t));
>
>                                Log(2, "Sending info buffer to DBM");
>                                DbmClient->WriteBuffer(sendBuffer,
> sizeof(SiteData_t));
>
>                                delete[] sendBuffer;

Why allocate a new buffer?  Just send the original data directly:

    DbmClient->WriteBuffer(site, sizeof(SiteData_t));


> On the client side, the error log shows:
>
>     19:59:43.56: Sending updateHilltopInfo message to DBM
>     19:59:43.56: Read of ACK from DBM failed
>     19:59:43.56: Exception gnerated = Connection Closed Gracefully.

That is to be expected since the server disconnected the client when the
exception occured.


Gambit
Re: 'Out of memory' exception for a IdTCPServer
#5499
Author: Drew
Date: Thu, 12 Aug 2004 22:00
192 lines
6510 bytes
Thanks for these comments.

The code for Log() is as follows:

//--------------------------------------------------------------------------
-
void __fastcall RTRSvrThread::Log(int logLevel, char* logMsg)
{
    if ((ParentForm->logEnabled) & (logLevel <= ParentForm->logLevel))
    {
        struct time t;

        gettime(&t);
        lineToWrite.sprintf("%2d:%02d:%02d.%02d: ", t.ti_hour, t.ti_min,
t.ti_sec, t.ti_hund);

        lineToWrite = lineToWrite + AnsiString(logMsg);

        Synchronize(LogMsg);
    }
}
//--------------------------------------------------------------------------
-
void __fastcall RTRSvrThread::LogMsg()
{
    while (ParentForm->Memo1->Lines->Count > 1000)
    {
        ParentForm->Memo1->Lines->Delete(0);
    }
    ParentForm->Memo1->Lines->Add(lineToWrite);
}

I think that this is thread safe, is it not?

The code for the command handler that I suspect is as follows:

//--------------------------------------------------------------------------
-
void __fastcall RTRSvrThread::RtrServerUpdateHilltops(TIdCommand *ASender)
{
    Log(2, "Updating hilltop info from RTR");

    int msgType = ACK;

    ASender->Thread->Connection->WriteLn(msgType);
    Log(2, "ACKed updateHilltopInfo message to RTR");

    SiteData_t* thisSiteInfo;

    thisSiteInfo = new SiteData_t;

    ASender->Thread->Connection->ReadBuffer(thisSiteInfo,
sizeof(SiteData_t));

    {
        sprintf(msg, "Read hilltop info %d from RTR", thisSiteInfo->siteID);
        Log(2, msg);
    }

    // Use the point values returned by Rtr to update the database
    time_t time_now;

    time_now = time(NULL);

    UpdatePointValues(thisSiteInfo, time_now);

    // Now send a second ACK to Rtr to tell it that we have finished
updating the database
    ASender->Thread->Connection->WriteLn(msgType);
    Log(2, "ACKed hilltop data message to RTR");

    // Find this hilltop on the PollActiveQ.
    // Update the LastUpdate time and then move it
    // from the PollActiveQ to one of the Idle Qs

    SiteData_t* qHilltop;

    for (int i=0; i < PollActiveQ->Count; i++)
    {
        qHilltop = (SiteData_t*)PollActiveQ->Items[i];
        if (thisSiteInfo->siteID == qHilltop->siteID)
        {
            qHilltop->LastUpdate = time_now;

            NormalIdleQ->Add(qHilltop);
            PollActiveQ->Delete(i);
            break;
        }
    }

    // Finally delete the hilltop structure
    try
    {
        delete thisSiteInfo;
    }
    catch(...)
    {
            LPVOID lpMsgBuf;

            FormatMessage(
                FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL,
                GetLastError(),
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default
language
                (LPTSTR) &lpMsgBuf,
                0,
                NULL
            );

            // Display the string.
            MessageBox( NULL, (LPTSTR)lpMsgBuf, "GetLastError",
MB_OK|MB_ICONINFORMATION );

            // Free the buffer.
            LocalFree( lpMsgBuf );
    }
}

"Remy Lebeau (TeamB)" <gambit47.no.spam@no.spam.yahoo.com> wrote in message
news:411be31c$1@newsgroups.borland.com...
>
> "Drew" <aemsley@brightwell.org.uk> wrote in message
> news:411bdf12$1@newsgroups.borland.com...
>
> >     RtrServer->Active = true;
> >
> >     RtrServer->CommandHandlersEnabled = true;
>
> You should set up the command handlers before you activate the server, not
> afterwards.
>
> >     RtrServer->CommandHandlers->Add();
> >     RtrServer->CommandHandlers->Items[0]->Command = readRtrParams;
> >     RtrServer->CommandHandlers->Items[0]->OnCommand =
> > RtrServerReadRtrParams;
>
> You should use the return value of Add() instead of indexing the Items[]
> collection over and over:
>
>     TIdCommandHandler *Handler = RtrServer->CommandHandlers->Add();
>     Handler->Command = readRtrParams;
>     Handler->->OnCommand = RtrServerReadRtrParams;
>
> > void __fastcall RTRSvrThread::RtrServerDisconnect(TIdPeerThread
*AThread)
> > {
> >     Log(0, "Rtr Server disconnected");
> > }
>
> What exactly does Log() do?  Is its code thread-safe?
>
> > The error log shows the following:
> >
> >     19:59:43.56: Rtr Server exception: Out of memory
> >     19:59:43.56: Rtr server disconnected
>
> That suggests that one of your command handlers is probably where the
> exception is being thrown.  Can you please show the actual handler code?
>
> >                                char* sendBuffer;
> >
> >                                sendBuffer = new
char[sizeof(SiteData_t)];
> >
> >                                memcpy(sendBuffer, site,
> sizeof(SiteData_t));
> >
> >                                Log(2, "Sending info buffer to DBM");
> >                                DbmClient->WriteBuffer(sendBuffer,
> > sizeof(SiteData_t));
> >
> >                                delete[] sendBuffer;
>
> Why allocate a new buffer?  Just send the original data directly:
>
>     DbmClient->WriteBuffer(site, sizeof(SiteData_t));
>
>
> > On the client side, the error log shows:
> >
> >     19:59:43.56: Sending updateHilltopInfo message to DBM
> >     19:59:43.56: Read of ACK from DBM failed
> >     19:59:43.56: Exception gnerated = Connection Closed Gracefully.
>
> That is to be expected since the server disconnected the client when the
> exception occured.
>
>
> Gambit
>
>
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads