Problem with Socket under Linux...

John M McIntosh johnmci at smalltalkconsulting.com
Sun Apr 28 01:00:28 UTC 2002


>don't exactly help. I just don't understand a word of what you're trying
>to say. It may be that I'm just no native speaker but I just can't
>figure out what that is supposed to mean ;-(
>
>Cheers,
>   - Andreas

Well there is always the source code to look at, both the mac and the 
unix code, two different implementations in fact. Besides even with 
perhaps incomprehensible documentation it's a step up from lots of 
the code which has *no* documentation.

However I think what would be really interesting here is to change 
both the smalltalk code and the vm code to use what Craig did in 
Flow. Pass a method based semaphore down to the primitive call in 
question. It gets signaled once, or never on a timeout condition. 
Perhaps this is a cleaner solution.

But is there any interest in doing it?


At 1:29 AM +0200 4/28/02, Andreas Raab wrote:
>Also, I've been over your description many times and I just could not
>understand into what more common (e.g., BSD) terms most of it
>translates. Formulations like:
>
>  > The Read Semaphore is signaled when data arrives at
>  > the interrupt level for a socket and the trigger is true,
>  > the trigger is reset.The Read Semaphore trigger is set when
>  > the user calls sqlSocketReceiveDataAvailable and we do NOT have
>  > any data waiting to be read we of course return false from the
>routine.
>
>don't exactly help. I just don't understand a word of what you're trying
>to say.

Well let's look at the bsd unix code. I see pendingEvents contains 
the mask bits for the triggers, or my interest in having a semaphore 
signaled. The Mac VM will buffer incoming data until squeak reads it, 
so having the semaphore signaled a dozen times before we actually 
read things is counter productive so a "trigger" or indicator to 
indicate which semaphore should be signaled once was introduced, 
perhaps passing a semaphore around might be cleaner?


from the unix code.
/* answer whether the socket has data available for reading */

int sqSocketReceiveDataAvailable(SocketPtr s)
{
   if (!socketValid(s))
     return false;   //This was -1, but I believe that was shown to be incorrect
   if (SOCKETSTATE(s) == Connected)
     {
       if (socketReadable(SOCKET(s)))
	return true;
       PSP(s)->pendingEvents|= READ_NOTIFY;
       aioHandle(SOCKET(s), dataHandler, PSP(s), AIO_RW);
     }
   return false;
}

"The Read Semaphore trigger is set when the user calls 
sqlSocketReceiveDataAvailable and we do NOT have any data waiting to 
be read"

That happens at PSP(s)->pendingEvents|= READ_NOTIFY; after confirming 
the socket is not readable, versus of course taking the return true;

>and we do NOT have
>  any data waiting to be read we of course return false from the routine.

the routine does return false; versus the return true after 
confirming the socket is not readable. to continue lets look at

/***     asynchronous io handlers       ***/

/* Each handler must at least:
  *   - suspend further handling for the associated socket
  *   - signal its semaphore to indicate that the operation is complete
  */
void notify(privateSocketStruct *pss, int eventMask)
{
   int mask= pss->pendingEvents | eventMask;
   if (mask & CONN_NOTIFY) 
interpreterProxy->signalSemaphoreWithIndex((pss)->connSema);
   if (mask & READ_NOTIFY) 
interpreterProxy->signalSemaphoreWithIndex((pss)->readSema);
   if (mask & WRITE_NOTIFY) 
interpreterProxy->signalSemaphoreWithIndex((pss)->writeSema);
   pss->pendingEvents= 0;
}


Note the if (mask & READ_NOTIFY) that completes the

>The Read Semaphore is signaled when data arrives at
>  > the interrupt level for a socket and the trigger is true,
>  the trigger is reset

which is the reset piece.

  pss->pendingEvents= 0;

But I'll note Ian changed the code a few days ago to

  void notify(privateSocketStruct *pss, int eventMask)
  {
    int mask= pss->pendingEvents & eventMask;
    if (mask & CONN_NOTIFY) 
interpreterProxy->signalSemaphoreWithIndex((pss)->connSema);
    if (mask & READ_NOTIFY) 
interpreterProxy->signalSemaphoreWithIndex((pss)->readSema);
    if (mask & WRITE_NOTIFY) 
interpreterProxy->signalSemaphoreWithIndex((pss)->writeSema);
    pss->pendingEvents&= ~mask;
  }

I'd bet turning off all the bits via pss->pendingEvents= 0; is wrong, 
since my description states "and the trigger is true, the trigger is 
reset." done by  pss->pendingEvents&= ~mask; (no?) versus resetting 
all the triggers (=0).

the notify gets called from

/* read or write data transfer is now possible for the socket */

static void dataHandler(void *pssIn, int readFlag, int writeFlag, int errFlag)
{
   privateSocketStruct *pss = (privateSocketStruct *)pssIn;
   sockSuspend(pss);

   FPRINTF((stderr, "dataHandler(%d,%d,%d)\n", pss->s, errFlag, readFlag));
   if (errFlag)
     /* error: almost certainly "connection closed by peer" */
     pss->sockState= OtherEndClosed;
   notify(pss, (readFlag ? READ_NOTIFY : WRITE_NOTIFY));
}

which was set via the aioHandle in the sqSocketReceiveDataAvailable. 
I'd guess that is the "data arrives at the interrupt level for a 
socket" part of equation.

Mmm I'll admit I'm not a doc writer, so if someone who is a doc 
writer wants to take the mac and unix code and the docs and create a 
easy to understand swiki of the magic that is going on. I'll help in 
the translation.

-- 
--
===========================================================================
John M. McIntosh <johnmci at smalltalkconsulting.com> 1-800-477-2659
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================



More information about the Squeak-dev mailing list