I have a problem involving multiple threads and trying to create a table after its been dropped. Perhaps I'm doing something wrong. Here is the jist.
In the main thread, I open a connection to database and create a timer function and start a worker thread. The worker thread establishes its own separate connection to database. The worker thread creates a table and then signals the main thread. The timer function in the main thread drops the table and signals back to the worker thread. The worker thread creates the table again and receives no error. However, if the worker thread tries to insert a record into that table, I get back a SQLITE_ERROR error. I have recreated this under Windows in a minimal test app. If it fails, it will display a message box saying "Why doesn't this work?" Create a dialog based MFC app using the VC6.0 wizard and add the following (assumes the class is called CLITEERRDlg). In the dialog include file add the following public member functions: ~CLITEERRDlg(); static UINT WorkerFcn(LPVOID pParam); static void CALLBACK OnTimerMain(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime); bool IsDead() const { return m_bWorkerDie; } And after the declaration of m_hIcon, add the following declarations: CWinThread* m_pWorkerThread; HANDLE m_hWorkerEvent; bool m_bWorkerDie; sqlite3* pMainDB; sqlite3* pWorkerDB; bool m_bDropTable; UINT_PTR m_uDBTimer; bool m_bAddTable; In the dialog cpp file, add the following to the constructor: m_pWorkerThread = NULL; m_hWorkerEvent = NULL; m_bWorkerDie = false; pWorkerDB = NULL; m_bDropTable = false; m_uDBTimer = 0; m_bAddTable = false; And add the following in the TODO section of the OnInitDialog function: int errCode = sqlite3_open("TEST.DB", &pMainDB); ASSERT(errCode == SQLITE_OK); m_hWorkerEvent = CreateEvent(NULL, FALSE, FALSE, NULL); ASSERT(m_hWorkerEvent != NULL); m_pWorkerThread = AfxBeginThread(CLITEERRDlg::WorkerFcn, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); ASSERT(m_pWorkerThread != NULL); m_pWorkerThread->m_bAutoDelete = FALSE; // prevents destroying CWinthread object upon thread termination! m_pWorkerThread->ResumeThread(); m_uDBTimer = ::SetTimer(NULL, 0, 500, CLITEERRDlg::OnTimerMain); And add these three functions: CLITEERRDlg::~CLITEERRDlg() { ::KillTimer(NULL, m_uDBTimer); m_uDBTimer = 0; m_bWorkerDie = true; if (m_hWorkerEvent != NULL) SetEvent(m_hWorkerEvent); if (m_pWorkerThread != NULL) { m_pWorkerThread->ResumeThread(); // Raise the thread's priority m_pWorkerThread->SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL); // Now wait for the thread to kill itself WaitForSingleObject(m_pWorkerThread->m_hThread, INFINITE); delete m_pWorkerThread; } if (m_hWorkerEvent != NULL) CloseHandle(m_hWorkerEvent); if (pMainDB != NULL) sqlite3_close(pMainDB); } #define THREAD_SANITY 5000 UINT CLITEERRDlg::WorkerFcn(LPVOID pParam) { CLITEERRDlg* pDB = (CLITEERRDlg*)pParam; if (pDB == NULL || pDB->IsDead()) return 0; int errCode = sqlite3_open("TEST.DB", &pDB->pWorkerDB); ASSERT (errCode == SQLITE_OK); errCode = sqlite3_exec(pDB->pWorkerDB, "CREATE TABLE IF NOT EXISTS TESTTABLE (KEY VARCHAR(32))", NULL, NULL, NULL); ASSERT(errCode == SQLITE_OK); pDB->m_bDropTable = true; // change this to m_bAddTable and there is no failure below DWORD dwStatus = ::WaitForSingleObject(pDB->m_hWorkerEvent, THREAD_SANITY); while (WAIT_OBJECT_0 == dwStatus || WAIT_TIMEOUT == dwStatus) { if (pDB->IsDead()) break; if (pDB->m_bAddTable) { pDB->m_bAddTable = false; errCode = sqlite3_exec(pDB->pWorkerDB, "CREATE TABLE IF NOT EXISTS TESTTABLE (KEY VARCHAR(32))", NULL, NULL, NULL); ASSERT(errCode == SQLITE_OK); errCode = sqlite3_exec(pDB->pWorkerDB, "INSERT INTO TESTTABLE (KEY) VALUES ('123456')", NULL, NULL, NULL); if (errCode != SQLITE_OK) // returned SQLITE_ERROR { AfxMessageBox("Why doesn't this work?"); return 0; } } dwStatus = ::WaitForSingleObject(pDB->m_hWorkerEvent, THREAD_SANITY); } sqlite3_close(pDB->pWorkerDB); return 0; } void CALLBACK CLITEERRDlg::OnTimerMain(HWND, UINT, UINT, DWORD) { extern CLITEERRApp theApp; CLITEERRDlg* pDlg = (CLITEERRDlg*)theApp.m_pMainWnd; if (pDlg != NULL) { if (pDlg->m_bDropTable) { pDlg->m_bDropTable = false; int errCode = sqlite3_exec(pDlg->pMainDB, "DROP TABLE IF EXISTS TESTTABLE", NULL, NULL, NULL); ASSERT(errCode == SQLITE_OK); pDlg->m_bAddTable = true; SetEvent(pDlg->m_hWorkerEvent); } } }