[108] in 6.033-lab
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.