Stop trying to flush on broken sockets marked for close.

svn:r1163
This commit is contained in:
Nick Mathewson 2004-02-28 19:14:11 +00:00
parent 80410fa8dc
commit f039eca658
4 changed files with 27 additions and 9 deletions

View File

@ -132,6 +132,10 @@ buf_t *buf_new()
return buf_new_with_capacity(INITIAL_BUF_SIZE); return buf_new_with_capacity(INITIAL_BUF_SIZE);
} }
void buf_clear(buf_t *buf)
{
buf->datalen = 0;
}
size_t buf_datalen(const buf_t *buf) size_t buf_datalen(const buf_t *buf)
{ {

View File

@ -141,6 +141,22 @@ void connection_free_all(void) {
connection_free(carray[i]); connection_free(carray[i]);
} }
/* Close the underlying socket for conn, so we don't try to flush it.
* Must be used in conjunction with connection_mark_for_close
*/
void connection_close_immediate(connection_t *conn)
{
assert_connection_ok(conn,0);
if (conn->s < 0) {
log_fn(LOG_WARN,"Attempt to close already-closed connection.");
return;
}
close(conn->s);
conn->s = -1;
buf_clear(conn->outbuf);
conn->outbuf_flushlen = 0;
}
int int
_connection_mark_for_close(connection_t *conn, char reason) _connection_mark_for_close(connection_t *conn, char reason)
{ {
@ -355,8 +371,7 @@ static void listener_close_if_present(int type) {
type == CONN_TYPE_DIR_LISTENER); type == CONN_TYPE_DIR_LISTENER);
conn = connection_get_by_type(type); conn = connection_get_by_type(type);
if (conn) { if (conn) {
close(conn->s); connection_close_immediate(conn);
conn->s = -1;
connection_mark_for_close(conn,0); connection_mark_for_close(conn,0);
} }
} }
@ -414,9 +429,7 @@ int connection_handle_read(connection_t *conn) {
router_mark_as_down(conn->nickname); router_mark_as_down(conn->nickname);
} }
/* There's a read error; kill the connection.*/ /* There's a read error; kill the connection.*/
/* XXX This is the place. We need to somehow indicate to connection_close_immediate(conn); /* Don't flush; connection is dead. */
* conn that it should never try to flush, or do anything
* with conn->s but close it. */
connection_mark_for_close(conn, END_STREAM_REASON_MISC); connection_mark_for_close(conn, END_STREAM_REASON_MISC);
return -1; return -1;
} }

View File

@ -221,10 +221,10 @@ static void conn_close_if_marked(int i) {
assert_connection_ok(conn, time(NULL)); assert_connection_ok(conn, time(NULL));
if(conn->marked_for_close) { if(conn->marked_for_close) {
log_fn(LOG_INFO,"Cleaning up connection (fd %d).",conn->s); log_fn(LOG_INFO,"Cleaning up connection (fd %d).",conn->s);
if(conn->s >= 0) { /* -1 means it's an incomplete edge connection */ if(conn->s >= 0) {
/* -1 means it's an incomplete edge connection, or that the socket
* has already been closed as unflushable. */
/* FIXME there's got to be a better way to check for this -- and make other checks? */ /* FIXME there's got to be a better way to check for this -- and make other checks? */
/* XXX the below two calls to flush_buf should not happen if the
* conn got hung up on. */
if(connection_speaks_cells(conn)) { if(connection_speaks_cells(conn)) {
if(conn->state == OR_CONN_STATE_OPEN) if(conn->state == OR_CONN_STATE_OPEN)
flush_buf_tls(conn->tls, conn->outbuf, &conn->outbuf_flushlen); flush_buf_tls(conn->tls, conn->outbuf, &conn->outbuf_flushlen);

View File

@ -549,6 +549,7 @@ int find_on_inbuf(char *string, int string_len, buf_t *buf);
buf_t *buf_new(); buf_t *buf_new();
buf_t *buf_new_with_capacity(size_t size); buf_t *buf_new_with_capacity(size_t size);
void buf_free(buf_t *buf); void buf_free(buf_t *buf);
void buf_clear(buf_t *buf);
size_t buf_datalen(const buf_t *buf); size_t buf_datalen(const buf_t *buf);
size_t buf_capacity(const buf_t *buf); size_t buf_capacity(const buf_t *buf);
@ -637,7 +638,7 @@ int getconfig(int argc, char **argv, or_options_t *options);
connection_t *connection_new(int type); connection_t *connection_new(int type);
void connection_free(connection_t *conn); void connection_free(connection_t *conn);
void connection_free_all(void); void connection_free_all(void);
void connection_close_immediate(connection_t *conn);
int _connection_mark_for_close(connection_t *conn, char reason); int _connection_mark_for_close(connection_t *conn, char reason);
#define connection_mark_for_close(c,r) \ #define connection_mark_for_close(c,r) \