From 47d2a1ee8f978a87566a194e38ca49f18f65ebe2 Mon Sep 17 00:00:00 2001 From: Jordan Lee Date: Thu, 31 Jan 2013 17:39:06 +0000 Subject: [PATCH] (libT) add assertions to check that block-writing functions are only invoked in the libtransmission thread --- libtransmission/cache.c | 3 ++ libtransmission/fail.sh | 8 ++++ libtransmission/move-test.c | 74 +++++++++++++++++++++++++++---------- libtransmission/torrent.c | 5 ++- 4 files changed, 70 insertions(+), 20 deletions(-) create mode 100755 libtransmission/fail.sh diff --git a/libtransmission/cache.c b/libtransmission/cache.c index 9ec276099..43af2358f 100644 --- a/libtransmission/cache.c +++ b/libtransmission/cache.c @@ -21,6 +21,7 @@ #include "peer-common.h" /* MAX_BLOCK_SIZE */ #include "ptrarray.h" #include "torrent.h" +#include "trevent.h" #include "utils.h" #define MY_NAME "Cache" @@ -333,6 +334,8 @@ tr_cacheWriteBlock (tr_cache * cache, { struct cache_block * cb = findBlock (cache, torrent, piece, offset); + assert (tr_amInEventThread (torrent->session)); + if (cb == NULL) { cb = tr_new (struct cache_block, 1); diff --git a/libtransmission/fail.sh b/libtransmission/fail.sh new file mode 100755 index 000000000..22a6171ec --- /dev/null +++ b/libtransmission/fail.sh @@ -0,0 +1,8 @@ +err=0 +count=0 +while [ $err -eq 0 ]; do + count=$((count+1)) + echo starting run number $count + make check + err=$? +done diff --git a/libtransmission/move-test.c b/libtransmission/move-test.c index 5f2ec99c6..4f28a2cbc 100644 --- a/libtransmission/move-test.c +++ b/libtransmission/move-test.c @@ -13,6 +13,7 @@ #include "transmission.h" #include "cache.h" #include "resume.h" +#include "trevent.h" #include "torrent.h" /* tr_isTorrent() */ #include "utils.h" /* tr_mkdirp() */ #include "variant.h" @@ -23,6 +24,13 @@ **** ***/ +#define verify_and_block_until_done(tor) \ + do { \ + do { tr_wait_msec (10); } while (tor->verifyState != TR_VERIFY_NONE); \ + tr_torrentVerify (tor); \ + do { tr_wait_msec (10); } while (tor->verifyState != TR_VERIFY_NONE); \ + } while (0) + static void zeroes_completeness_func (tr_torrent * torrent UNUSED, tr_completeness completeness, @@ -41,9 +49,30 @@ zeroes_completeness_func (tr_torrent * torrent UNUSED, tr_free (path); \ } while (0) +struct test_incomplete_dir_is_subdir_of_download_dir_data +{ + tr_torrent * tor; + tr_block_index_t block; + tr_piece_index_t pieceIndex; + uint32_t offset; + struct evbuffer * buf; + bool done; +}; + +static void +test_incomplete_dir_is_subdir_of_download_dir_threadfunc (void * vdata) +{ + struct test_incomplete_dir_is_subdir_of_download_dir_data * data = vdata; + tr_cacheWriteBlock (session->cache, data->tor, 0, data->offset, data->tor->blockSize, data->buf); + tr_torrentGotBlock (data->tor, data->block); + data->done = true; +} + + static int test_incomplete_dir_is_subdir_of_download_dir (void) { + size_t i; char * incomplete_dir; tr_torrent * tor; tr_completeness completeness; @@ -65,36 +94,43 @@ test_incomplete_dir_is_subdir_of_download_dir (void) check_file_location (tor, 1, tr_buildPath(incomplete_dir, tor->info.files[1].name, NULL)); check_int_eq (tor->info.pieceSize, tr_torrentStat(tor)->leftUntilDone); + completeness = completeness_unset; + tr_torrentSetCompletenessCallback (tor, zeroes_completeness_func, &completeness); + /* now finish writing it */ { - uint32_t offset; - tr_block_index_t first, last, i; - struct evbuffer * buf = evbuffer_new (); + tr_block_index_t first, last; char * zero_block = tr_new0 (char, tor->blockSize); + struct test_incomplete_dir_is_subdir_of_download_dir_data data; - completeness = completeness_unset; - tr_torrentSetCompletenessCallback (tor, zeroes_completeness_func, &completeness); + data.tor = tor; + data.pieceIndex = 0; + data.buf = evbuffer_new (); - tr_torGetPieceBlockRange (tor, 0, &first, &last); - for (offset=0, i=first; i<=last; ++i, offset+=tor->blockSize) + tr_torGetPieceBlockRange (tor, data.pieceIndex, &first, &last); + for (i=first; i<=last; ++i) { - evbuffer_add (buf, zero_block, tor->blockSize); - tr_cacheWriteBlock (session->cache, tor, 0, offset, tor->blockSize, buf); - tr_torrentGotBlock (tor, i); + evbuffer_add (data.buf, zero_block, tor->blockSize); + data.block = i; + data.done = false; + data.offset = data.block * tor->blockSize; + tr_runInEventThread (session, test_incomplete_dir_is_subdir_of_download_dir_threadfunc, &data); + do { tr_wait_msec(50); } while (!data.done); } - sync (); - tr_torrentVerify (tor); - while ((completeness==completeness_unset) && (time(NULL)<=deadline)) - tr_wait_msec (50); - check_int_eq (TR_SEED, completeness); - for (i=0; iinfo.fileCount; ++i) - check_file_location (tor, i, tr_buildPath (downloadDir, tor->info.files[i].name, NULL)); - - evbuffer_free (buf); + evbuffer_free (data.buf); tr_free (zero_block); } + verify_and_block_until_done (tor); + check_int_eq (0, tr_torrentStat(tor)->leftUntilDone); + + while ((completeness==completeness_unset) && (time(NULL)<=deadline)) + tr_wait_msec (50); + + check_int_eq (TR_SEED, completeness); + for (i=0; iinfo.fileCount; ++i) + check_file_location (tor, i, tr_buildPath (downloadDir, tor->info.files[i].name, NULL)); /* cleanup */ tr_torrentRemove (tor, true, remove); diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index d48c6e222..7ba93015e 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -2950,7 +2950,7 @@ setLocation (void * vdata) { /* blow away the leftover subdirectories in the old location */ if (do_move) - tr_torrentDeleteLocalData (tor, remove); + tr_torrentDeleteLocalData (tor, remove); /* set the new location and reverify */ tr_torrentSetDownloadDir (tor, location); @@ -3066,6 +3066,9 @@ tr_torrentGotBlock (tr_torrent * tor, tr_block_index_t block) { const bool block_is_new = !tr_cpBlockIsComplete (&tor->completion, block); + assert (tr_isTorrent (tor)); + assert (tr_amInEventThread (tor->session)); + if (block_is_new) { tr_piece_index_t p;