If we write the annotation but not the microdescriptor, rewind.

This fixes bug 9047 (and some parts of 9031, 8922, 8883 that weren't
fixed in 8822).  Bugfix on 0.2.2.6-alpha.
This commit is contained in:
Nick Mathewson 2013-06-13 12:29:01 -04:00
parent 25dddf7a8f
commit caa0d15c49
4 changed files with 32 additions and 6 deletions

6
changes/bug9047 Normal file
View File

@ -0,0 +1,6 @@
o Minor bugfixes:
- If for some reason we fail to write a microdescriptor while
rebuilding the cache, do not let the annotations from that
microdescriptor linger in the cache file, and do not let the
microdescriptor stay recorded as present in its old location.
Fixes bug 9047; bugfix on 0.2.2.6-alpha.

View File

@ -900,6 +900,18 @@ tor_fd_seekend(int fd)
#endif #endif
} }
/** Move <b>fd</b> to position <b>pos</b> in the file. Return -1 on error, 0
* on success. */
int
tor_fd_setpos(int fd, off_t pos)
{
#ifdef _WIN32
return _lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
#else
return lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
#endif
}
#undef DEBUG_SOCKET_COUNTING #undef DEBUG_SOCKET_COUNTING
#ifdef DEBUG_SOCKET_COUNTING #ifdef DEBUG_SOCKET_COUNTING
/** A bitarray of all fds that should be passed to tor_socket_close(). Only /** A bitarray of all fds that should be passed to tor_socket_close(). Only

View File

@ -411,6 +411,7 @@ tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
void tor_lockfile_unlock(tor_lockfile_t *lockfile); void tor_lockfile_unlock(tor_lockfile_t *lockfile);
off_t tor_fd_getpos(int fd); off_t tor_fd_getpos(int fd);
int tor_fd_setpos(int fd, off_t pos);
int tor_fd_seekend(int fd); int tor_fd_seekend(int fd);
#ifdef _WIN32 #ifdef _WIN32

View File

@ -74,7 +74,7 @@ static ssize_t
dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out) dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out)
{ {
ssize_t r = 0; ssize_t r = 0;
size_t written; ssize_t written;
if (md->body == NULL) { if (md->body == NULL) {
*annotation_len_out = 0; *annotation_len_out = 0;
return 0; return 0;
@ -99,10 +99,10 @@ dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out)
md->off = tor_fd_getpos(fd); md->off = tor_fd_getpos(fd);
written = write_all(fd, md->body, md->bodylen, 0); written = write_all(fd, md->body, md->bodylen, 0);
if (written != md->bodylen) { if (written != (ssize_t)md->bodylen) {
log_warn(LD_DIR, log_warn(LD_DIR,
"Couldn't dump microdescriptor (wrote %lu out of %lu): %s", "Couldn't dump microdescriptor (wrote %ld out of %lu): %s",
(unsigned long)written, (unsigned long)md->bodylen, (long)written, (unsigned long)md->bodylen,
strerror(errno)); strerror(errno));
return -1; return -1;
} }
@ -456,8 +456,15 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
size = dump_microdescriptor(fd, md, &annotation_len); size = dump_microdescriptor(fd, md, &annotation_len);
if (size < 0) { if (size < 0) {
/* XXX handle errors from dump_microdescriptor() */ if (md->saved_location != SAVED_IN_CACHE)
/* log? return -1? die? coredump the universe? */ tor_free(md->body);
md->saved_location = SAVED_NOWHERE;
md->off = 0;
md->bodylen = 0;
md->no_save = 1;
/* rewind, in case it was a partial write. */
tor_fd_setpos(fd, off);
continue; continue;
} }
tor_assert(((size_t)size) == annotation_len + md->bodylen); tor_assert(((size_t)size) == annotation_len + md->bodylen);