jeudi 12 février 2015

64-bit Windows 7 Recursive directory removal fails when deleting a directory containing Sqlite

I have a test case (stripped version of bigger application) which fails sporadically on Windows 7 machine when trying to remove directory or file. It is using native Windows APIs. Test performs following steps --



  1. Create directory.

  2. Create a sqlite3 db in the directory created by step#1.

  3. Create a table in the DB.

  4. Close the DB.

  5. If any DB journal file is present, delete it.

  6. Delete the DB file.

  7. Delete the directory.


If you skip step#1, then test would run fine. If you add delay between step#4 and step#5, then test would run fine.



#include <windows.h>
#include <string>
#include <iostream>
#include <stdio.h>
#include <direct.h>
#include <sqlite3.h>
#include <io.h>
using namespace std;

bool sleep_for_sometime = false;
bool create_table = false;
bool runTest()
{
char cwdpath[1024] = {'\0'};
if (_getcwd(cwdpath, 1023) == NULL) return false;
string testpath(cwdpath);
testpath += "/test_dir";
_mkdir(testpath.c_str());
string dbpath = testpath + "/test.db";
sqlite3 *db = NULL;
if (sqlite3_open(dbpath.c_str(), &db) != SQLITE_OK) return false;
// Create table.
if (create_table) {
string sql = "CREATE TABLE COMPANY(" \
"ID INT PRIMARY KEY NOT NULL," \
"NAME TEXT NOT NULL," \
"AGE INT NOT NULL)";
char *zErrMsg = 0;
if (sqlite3_exec(db, sql.c_str(), NULL, 0, &zErrMsg) != SQLITE_OK) {
sqlite3_close(db);
cerr << "Could not create table: " << zErrMsg << endl;
return false;
}
}
sqlite3_close(db);
if (sleep_for_sometime) {
Sleep(100);
}
string journal_file = dbpath + "-journal";
string journal_error = journal_file + " failed";
if (_access(journal_file.c_str(), 06) == 0) {
if (_unlink(journal_file.c_str()) != 0) {
perror(journal_error.c_str());
return false;
}
cout << "journal file --" << journal_file << endl;
}
string db_error = dbpath + " failed";
if (_unlink(dbpath.c_str()) != 0) {
perror(db_error.c_str());
return false;
}
string dir_error = testpath + " failed";
if (_rmdir(testpath.c_str()) != 0) {
perror(dir_error.c_str());
return false;
}
return true;
}
int main(int argc, char **argv)
{
cout << "Usage: ./projtest 1 1" << endl;
cout << "------If you pass two parameter, then always create table and sleep for some time." << endl;
cout << "Usage: ./projtest 1" << endl;
cout << "------If you pass one parameter, then always create table, but don't sleep." << endl;
cout << "Usage: ./projtest" << endl;
cout << "------If you don't pass any parameter, then don't create table and don't sleep." << endl;
if (argc == 3) {
sleep_for_sometime = true;
create_table = true;
} else if (argc == 2) {
create_table = true;
sleep_for_sometime = false;
} else {
create_table = false;
sleep_for_sometime = false;
}
for (int i = 0; i < 500 ; i++) {
if (! runTest()) {
cerr << "Err in runTest trial --" << i+1 << endl;
return 1;
}
}
return 0;
}

Aucun commentaire:

Enregistrer un commentaire