[84] in 6.033-lab
Lab 1 Proxy
daemon@ATHENA.MIT.EDU (Constantine P Sapuntzakis)
Thu Apr 2 17:11:52 1998
Date: Thu, 2 Apr 1998 17:11:39 -0500 (EST)
From: Constantine P Sapuntzakis <csapuntz@MIT.EDU>
To: 6.033-lab@MIT.EDU
This document describes some of the common problems we found with the
graded TCP proxies. Many of you on the list have already received a
personal e-mail with a substantially similar document. This document is
for the benefit of those on the list who are just listening.
Source code for a working proxy can be found in the 6.033 locker in
/mit/6.033/lab/src/proxy.
Common problems
Busy waiting, also known as polling, was a common mistake in this
lab. Instead of waiting until the operating system inform them of some
event (e.g. the arrival of data), these programs repeatedly ask the
operating system for the status, looping until the event occurs. There
were many different ways of busy waiting:
1) Blatant: Programs just looped trying to read from client and server
until data appeared or was written
2) Select-based: Some programs managed to busy wait despite their use
of the select command. Many of these programs were constantly
select'ing for write, even when they had nothing to write to the
socket. Selecting for write asks whether there's room to write to
the server and this is often the case. As such, select returns
immediately, but since the programs having nothing to do, they call
select again, looping.
3) Callbacks (i.e. async.c): Many programs had callbacks registered
for writing when they had no data to write. Since the connection to
the server is usually ready-to-write, this callback was being
constantly executed. Many people forgot to deactivate callbacks
(using cb_free) when they were no longer interested in writing or
reading.
The second most common mistake was blocking on writes. This behavior
is extremely bad as it can lead to deadlock. In some designs, when the
proxy is blocked on the write, it cannot accept data in the other
direction, thus leading to such a deadlock. For example, deadlock
occurs when the proxy is trying to write data to the client but the
client is not accepting any and blocked trying to write data to the
proxy.
Another common mistake was forgetting to close file descriptors, which
caused some of the proxies to quickly run out and fail.
Testing
To determine whether a proxy functioned correctly, it was run
using a testing program, which exercised the proxy. The testing
program is available online in /mit/6.033/lab/src/testproxy. An
example proxy is included in that directory and another in
/mit/6.033/lab/src/proxy.
The testing program exercised the proxy in six separate phases with some
of the phases being subdivided:
Phase 1 - Ascertain how many simultaneous connections the proxy supports
Phase 2 - Make sure data passes bidirectionally without corruption or truncation
A) 1 connection, 1 simultaneous client
B) 200 connections, 1 simultaneous client
C) 200 connections, 20 simultaneous clients
Phase 3 - Proxy handles end-of-file condition correctly
A) 1 connection, 1 simultaneous client
B) 200 connections, 1 simultaneous client
C) 200 connections, 20 simultaneous clients
Phase 4 - Proxy handles unbounded writes by server without commensurate reads
A) Client->Server
B) Server->Client
Phase 5 - Proxy deals with server suddenly dying and leaving data in the pipe
Phase 6 - Proxy does not block on writes to server or client
-Costa