[108] in 6.033-lab

home help back first fref pref prev next nref lref last post

Re: 6.033 lab

daemon@ATHENA.MIT.EDU (Kevin Fu)
Thu Feb 18 11:23:17 1999

To: Roger Hu <rogerh@MIT.EDU>, stanhu@MIT.EDU
Cc: 6.033-lab@MIT.EDU
In-Reply-To: Your message of Thu, 18 Feb 1999 08:41:22 -0500.
             <4.1.19990218083812.00a50880@po8.mit.edu> 
Date: Thu, 18 Feb 1999 11:23:05 EST
From: Kevin Fu <fubob@MIT.EDU>

Hi,

Good questions.  Hopefully this will clarify.

1.) Yes, it sounds wise to compile and link async.c directly with
multifinger.c during your development.  This will help in your
debugging.  Just remember to create the library when you finish the
project.

2.) You are somewhat correct about the liklihood of a "race
condition," but it's not really a race condition.  By definition,
select() may destroy the contents of the fd_set arguments (&rfds,
&wfds).  From the man page on select():

     On successful completion, the  objects  pointed  to  by  the
     readfs,  writefs,  and  errorfds  arguments  are modified to
     indicate which file descriptors are ready for reading, ready
     for  writing,  or  have  an error condition pending, respec-
     tively.  For  each  file  descriptor  less  than  nfds,  the
     corresponding bit will be set on successful completion if it
     was set on input and the associated condition  is  true  for
     that file descriptor.

You should use temporary variables as arguments to select() in order
to preserve the list of your callbacks in rfds and wfds.  Copy these
variables to a temporary location with either memcpy or a simple
assignment (e.g., temp_wfds = wfds;).  It's not such a big pitfall for
large writes/reads.  In short writes/reads, it might become a
bottleneck.  

3.) There is, however, a race-like condition possible in cb_check().
One callback may call cb_free() on a callback of a higher numbered
file descriptor.  What should happen if select() returns with two file
descriptors ready for callbacks?  It should execute the first callback
then the second callback, right?  Not exactly.  If the first callback
cb_free()'s the second callback, you will only execute the first
callback.  In other words, after select() returns with a list of ready
file descriptors, you will need to make additional tests.  First,
check your temporary variables:

	if (FD_ISSET(fd, &temp_wfds)) ...

Then double check the original callback list:

	if (FD_ISSET(fd, &wfds)) ...

If both tests pass, you will execute the function in the callback.

--------
Kevin E. Fu (fubob@mit.edu)
PGP key: finger fubob@monk.mit.edu

>A suggestion next time is to have people work with a merged async.c and the
>multifinger.c into one file -- at least temporarily.  Otherwise, you can't
>insert printf() statements in the async.c code to test for the corruption
>and it's impossible to debug.
>
>Stan's analysis is dead-on...the moment I stopped using the wfds and rfds
>immediately, the library worked brillantly.
>
>Is there a better alternative than to using memcpy()?   Otherwise, this is
>going to be a huge pitfall....
>
>Roger
>
>X-Sender: stanhu@po7.mit.edu (Unverified)
>X-Mailer: QUALCOMM Windows Eudora Pro Version 4.1 
>Date: Wed, 17 Feb 1999 13:21:43 -0500
>To: rogerh@MIT.EDU
>From: Stanley Hu <stanhu@MIT.EDU>
>Subject: race condition?
>:
>:
>
>I think the problem in cb_check is the one that I mentioned earlier.  I
>think there is a possible race condition when you use select directly with
>the rfds and wfds structures.  Suppose you have two finger requests going
>out.  The first socket is ready for writing, but the second one isn't.  For
>the second socket, select will set the socket status bit on wfds to 0, even
>though you still are interested in writing to it.  Unless both sockets are
>ready when the select is called, the second socket won't ever fire because
>it's been "deactivated."
>
>Hence, you need to use separate rfds and wfds structures when calling
>select just so it doesn't permanently alter your callback info.

home help back first fref pref prev next nref lref last post