Skip to content

Commit

Permalink
fix crash during w_root_perform_age_out
Browse files Browse the repository at this point in the history
Finally got around to reproducing this.  Turns out to be a simple
matter of iterator invalidation that we can avoid by simply restarting
our iteration.

Addresses #57
  • Loading branch information
wez committed Mar 29, 2015
1 parent 34bede7 commit ab7be81
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
13 changes: 8 additions & 5 deletions root.c
Original file line number Diff line number Diff line change
Expand Up @@ -1373,19 +1373,22 @@ static void age_out_file(w_root_t *root, struct watchman_file *file);
static void age_out_dir(w_root_t *root, struct watchman_dir *dir)
{
w_ht_iter_t i;

if (dir->files && w_ht_first(dir->files, &i)) do {
// Since age_out_file deletes itself from dir->files, it will
// invalidate the iterator, so we have to restart our iteration each time.
while (dir->files && w_ht_first(dir->files, &i)) {
struct watchman_file *file = w_ht_val_ptr(i.value);

assert(!file->exists);
age_out_file(root, file);
} while (w_ht_next(dir->files, &i));
}

if (dir->dirs && w_ht_first(dir->dirs, &i)) do {
// Since age_out_dir deletes itself from dir->dirs, it will
// invalidate the iterator, so we have to restart our iteration each time.
while (dir->dirs && w_ht_first(dir->dirs, &i)) {
struct watchman_dir *child = w_ht_val_ptr(i.value);

age_out_dir(root, child);
} while (w_ht_next(dir->dirs, &i));
}

// This will implicitly call delete_dir() which will tear down
// the files and dirs hashes
Expand Down
15 changes: 15 additions & 0 deletions tests/integration/age.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ function ($list) {
));
sort($res['files']);
$this->assertEqual(array('b.txt', 'c.txt'), $res['files']);

// Let's stress it a bit
mkdir("$root/dir");
for ($i = 0; $i < 100; $i++) {
touch("$root/stress-$i");
touch("$root/dir/$i");
}
for ($i = 0; $i < 100; $i++) {
unlink("$root/stress-$i");
unlink("$root/dir/$i");
}
rmdir("$root/dir");
$this->assertFileList($root, array('b.txt', 'c.txt'));
$this->watchmanCommand('debug-ageout', $root, 0);
$this->assertFileList($root, array('b.txt', 'c.txt'));
}
}

Expand Down

0 comments on commit ab7be81

Please sign in to comment.