(libT) add assertions to check that block-writing functions are only invoked in the libtransmission thread

This commit is contained in:
Jordan Lee 2013-01-31 17:39:06 +00:00
parent 65859df967
commit 47d2a1ee8f
4 changed files with 70 additions and 20 deletions

View File

@ -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);

8
libtransmission/fail.sh Executable file
View File

@ -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

View File

@ -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; i<tor->info.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; i<tor->info.fileCount; ++i)
check_file_location (tor, i, tr_buildPath (downloadDir, tor->info.files[i].name, NULL));
/* cleanup */
tr_torrentRemove (tor, true, remove);

View File

@ -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;