Refactor _write_socket

Call real_write_all in write_lines and write_line.
This should fix debian bug #542291.
BIG thanks to Zygo Blaxell.
This commit is contained in:
Arnaud Cornet 2009-08-19 22:02:56 +02:00
parent 7546daa276
commit 70fbf99c7f
1 changed files with 29 additions and 34 deletions

View File

@ -235,46 +235,42 @@ static int _write_socket(connection_t *cn, char *message)
ssize_t count; ssize_t count;
size = strlen(message); size = strlen(message);
if (size == 0)
return WRITE_OK;
/* loop if we wrote some data but not everything, or if error is
* EINTR */
do { do {
count = write(cn->handle, ((const char *)message) + tcount, count = write(cn->handle, ((const char *)message) + tcount,
size - tcount); size - tcount);
if (count > 0) { if (count > 0) {
tcount += count; tcount += count;
if (tcount == size) if (tcount == size)
break; return WRITE_OK;
} }
} while (count < 0 && errno == EINTR); } while (count > 0 || (count < 0 && errno == EINTR));
#if 0 /* If we reach this point, we have a partial write */
if (count <= 0 && tcount > 0) assert(count != 0);
fatal("shit happens errno:%d count:%d tcount:%d (%s)\n", errno,
count, tcount, message);
#endif
if (tcount < size) {
/*
* if no fatal error, return WRITE_KEEP, which makes caller
* keep line in its FIFO
*
* Shitty: we might have written a partial line, so we hack the
* line...
* callers of _write_socket muse provide a writable memspace
*/
if (count < 0 && (errno == EAGAIN || errno == EINPROGRESS)) {
memmove(message, message + tcount, size - tcount + 1);
return WRITE_KEEP;
}
if (cn_is_connected(cn)) { /* if no fatal error, return WRITE_KEEP, which makes caller keep line
mylog(LOG_DEBUGVERB, "write(fd %d) : %s", cn->handle, * in its FIFO
strerror(errno)); *
connection_close(cn); * Shitty: we might have written a partial line, so we hack the line...
cn->connected = CONN_ERROR; * Callers of _write_socket muse provide a writable message
} */
mylog(LOG_DEBUGVERB, "write : %s", strerror(errno)); if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
return WRITE_ERROR; memmove(message, message + tcount, size - tcount + 1);
return WRITE_KEEP;
} }
mylog(LOG_DEBUGVERB, "%d/%d bytes sent !", tcount, size); /* other errors, EPIPE or worse, close the connection, repport error */
return WRITE_OK; if (cn_is_connected(cn)) {
if (errno != EPIPE)
mylog(LOG_INFO, "Broken socket: %s.", strerror(errno));
connection_close(cn);
cn->connected = CONN_ERROR;
}
mylog(LOG_DEBUGVERB, "write: %d, %s", cn->handle, strerror(errno));
return WRITE_ERROR;
} }
static int write_socket(connection_t *cn, char *line) static int write_socket(connection_t *cn, char *line)
@ -343,12 +339,9 @@ void write_line_fast(connection_t *cn, char *line)
r = write_socket(cn, nline); r = write_socket(cn, nline);
switch (r) { switch (r) {
case WRITE_KEEP: case WRITE_KEEP:
list_add_first(cn->outgoing, nline); cn->partial = nline;
break; break;
case WRITE_ERROR: case WRITE_ERROR:
cn->connected = CONN_ERROR;
free(nline);
break;
case WRITE_OK: case WRITE_OK:
free(nline); free(nline);
break; break;
@ -362,11 +355,13 @@ void write_line_fast(connection_t *cn, char *line)
void write_lines(connection_t *cn, list_t *lines) void write_lines(connection_t *cn, list_t *lines)
{ {
list_append(cn->outgoing, lines); list_append(cn->outgoing, lines);
real_write_all(cn);
} }
void write_line(connection_t *cn, char *line) void write_line(connection_t *cn, char *line)
{ {
list_add_last(cn->outgoing, bip_strdup(line)); list_add_last(cn->outgoing, bip_strdup(line));
real_write_all(cn);
} }
list_t *read_lines(connection_t *cn, int *error) list_t *read_lines(connection_t *cn, int *error)