Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a race condition in sqlite3_initialize(). (CVS 5310) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
70b2ed2afcf1757d1c58f3a83dad4a5f |
User & Date: | danielk1977 2008-06-26 08:29:34.000 |
Context
2008-06-26
| ||
10:41 | Change the OS_XXX pre-processor symbols to SQLITE_OS_XXX. Symbols "OS_UNIX", "OS_WIN", "OS_WINCE", "OS_OS2" and "OS_OTHER" are now "SQLITE_OS_UNIX", "SQLITE_OS_WIN", "SQLITE_OS_WINCE", "SQLITE_OS_OS2" and "SQLITE_OS_OTHER", respectively. (CVS 5311) (check-in: cdd4cf4ce2 user: danielk1977 tags: trunk) | |
08:29 | Fix a race condition in sqlite3_initialize(). (CVS 5310) (check-in: 70b2ed2afc user: danielk1977 tags: trunk) | |
02:53 | Documentation updates. No changes to code. (CVS 5309) (check-in: cdc4e75a9f user: drh tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.463 2008/06/26 08:29:34 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> #ifdef SQLITE_ENABLE_FTS3 # include "fts3.h" #endif |
︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 | ** this routine will be called automatically by key routines such as ** sqlite3_open(). ** ** This routine is a no-op except on its very first call for the process, ** or for the first call after a call to sqlite3_shutdown. */ int sqlite3_initialize(void){ int rc; if( sqlite3Config.isInit ) return SQLITE_OK; rc = sqlite3MutexInit(); if( rc==SQLITE_OK ){ | > > > > > > | > > > | < | < | < | > | < | < | > > > | | > | > > > > > > > > > > > > > > > > > > > > > > > > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | ** this routine will be called automatically by key routines such as ** sqlite3_open(). ** ** This routine is a no-op except on its very first call for the process, ** or for the first call after a call to sqlite3_shutdown. */ int sqlite3_initialize(void){ static int inProgress = 0; int rc; /* If SQLite is already initialized, this call is a no-op. */ if( sqlite3Config.isInit ) return SQLITE_OK; /* Make sure the mutex system is initialized. */ rc = sqlite3MutexInit(); if( rc==SQLITE_OK ){ /* Initialize the malloc() system and the recursive pInitMutex mutex. ** This operation is protected by the STATIC_MASTER mutex. */ sqlite3_mutex *pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(pMaster); if( !sqlite3Config.isMallocInit ){ rc = sqlite3MallocInit(); } if( rc==SQLITE_OK ){ sqlite3Config.isMallocInit = 1; if( !sqlite3Config.pInitMutex ){ sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){ rc = SQLITE_NOMEM; } } } sqlite3_mutex_leave(pMaster); if( rc!=SQLITE_OK ){ return rc; } /* Enter the recursive pInitMutex mutex. After doing so, if the ** sqlite3Config.isInit flag is true, then some other thread has ** finished doing the initialization. If the inProgress flag is ** true, then this function is being called recursively from within ** the sqlite3_os_init() call below. In either case, exit early. */ sqlite3_mutex_enter(sqlite3Config.pInitMutex); if( sqlite3Config.isInit || inProgress ){ sqlite3_mutex_leave(sqlite3Config.pInitMutex); return SQLITE_OK; } sqlite3StatusReset(); inProgress = 1; rc = sqlite3_os_init(); inProgress = 0; sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0); sqlite3_mutex_leave(sqlite3Config.pInitMutex); } return rc; } /* ** Undo the effects of sqlite3_initialize(). Must not be called while ** there are outstanding database connections or memory allocations or ** while any part of SQLite is otherwise in use in any thread. This ** routine is not threadsafe. Not by a long shot. */ int sqlite3_shutdown(void){ sqlite3_mutex_free(sqlite3Config.pInitMutex); sqlite3Config.pInitMutex = 0; sqlite3Config.isMallocInit = 0; sqlite3_os_end(); sqlite3MallocEnd(); sqlite3MutexEnd(); sqlite3Config.isInit = 0; return SQLITE_OK; } |
︙ | ︙ | |||
115 116 117 118 119 120 121 | */ int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while ** the SQLite library is in use. */ | | | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | */ int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while ** the SQLite library is in use. */ if( sqlite3Config.isInit ) return SQLITE_MISUSE; va_start(ap, op); switch( op ){ case SQLITE_CONFIG_SINGLETHREAD: { /* Disable all mutexing */ sqlite3Config.bCoreMutex = 0; sqlite3Config.bFullMutex = 0; |
︙ | ︙ |
Changes to src/os.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains OS interface code that is common to all ** architectures. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains OS interface code that is common to all ** architectures. ** ** $Id: os.c,v 1.117 2008/06/26 08:29:34 danielk1977 Exp $ */ #define _SQLITE_OS_C_ 1 #include "sqliteInt.h" #undef _SQLITE_OS_C_ /* ** The default SQLite sqlite3_vfs implementations do not allocate |
︙ | ︙ | |||
239 240 241 242 243 244 245 | /* ** Register a VFS with the system. It is harmless to register the same ** VFS multiple times. The new VFS becomes the default if makeDflt is ** true. */ int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ | < < < < | < < | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | /* ** Register a VFS with the system. It is harmless to register the same ** VFS multiple times. The new VFS becomes the default if makeDflt is ** true. */ int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ sqlite3_mutex *mutex = 0; #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); if( rc ) return rc; #endif mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(mutex); vfsUnlink(pVfs); if( makeDflt || vfsList==0 ){ pVfs->pNext = vfsList; vfsList = pVfs; }else{ pVfs->pNext = vfsList->pNext; |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.730 2008/06/26 08:29:34 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build |
︙ | ︙ | |||
1730 1731 1732 1733 1734 1735 1736 | int rc; /* Result code stored here */ } InitData; /* ** Structure containing global configuration data for the SQLite library. ** ** This structure also contains some state information. | < < < < < < | > > | 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 | int rc; /* Result code stored here */ } InitData; /* ** Structure containing global configuration data for the SQLite library. ** ** This structure also contains some state information. */ struct Sqlite3Config { int bMemstat; /* True to enable memory status */ int bCoreMutex; /* True to enable core mutexing */ int bFullMutex; /* True to enable full mutexing */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max heap requests sizes */ void *pScratch; /* Scratch memory */ int szScratch; /* Size of each scratch buffer */ int nScratch; /* Number of scratch buffers */ void *pPage; /* Page cache memory */ int szPage; /* Size of each page in pPage[] */ int nPage; /* Number of pages in pPage[] */ int isInit; /* True after initialization has finished */ int isMallocInit; /* True after malloc is initialized */ sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ }; /* ** Assuming zIn points to the first byte of a UTF-8 character, ** advance zIn to point to the first byte of the next UTF-8 character. */ #define SQLITE_SKIP_UTF8(zIn) { \ |
︙ | ︙ |
Changes to test/mutex1.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2008 June 17 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # | | | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # 2008 June 17 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # $Id: mutex1.test,v 1.5 2008/06/26 08:29:35 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl sqlite3_reset_auto_extension proc mutex_counters {varname} { upvar $varname var set var(total) 0 foreach {name value} [read_mutex_counters] { set var($name) $value incr var(total) $value } } #------------------------------------------------------------------------- # Tests mutex1-1.* test that sqlite3_config() returns SQLITE_MISUSE if # is called at the wrong time. And that the first time sqlite3_initialize # is called it obtains the 'static_master' mutex 3 times and a recursive # mutex (sqlite3Config.pInitMutex) twice. Subsequent calls are no-ops # that do not require any mutexes. # do_test mutex1-1.0 { install_mutex_counters 1 } {SQLITE_MISUSE} do_test mutex1-1.1 { db close |
︙ | ︙ | |||
60 61 62 63 64 65 66 | do_test mutex1-1.6 { sqlite3_initialize } {SQLITE_OK} do_test mutex1-1.7 { mutex_counters counters list $counters(total) $counters(static_master) | | | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | do_test mutex1-1.6 { sqlite3_initialize } {SQLITE_OK} do_test mutex1-1.7 { mutex_counters counters list $counters(total) $counters(static_master) } {6 3} do_test mutex1-1.8 { clear_mutex_counters sqlite3_initialize } {SQLITE_OK} do_test mutex1-1.9 { |
︙ | ︙ | |||
92 93 94 95 96 97 98 | serialized {fast recursive static_master static_mem static_prng} } { do_test mutex1.2.$mode.1 { catch {db close} sqlite3_shutdown sqlite3_config $mode } SQLITE_OK | | > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | serialized {fast recursive static_master static_mem static_prng} } { do_test mutex1.2.$mode.1 { catch {db close} sqlite3_shutdown sqlite3_config $mode } SQLITE_OK do_test mutex1.2.$mode.2 { sqlite3_initialize clear_mutex_counters sqlite3 db test.db catchsql { CREATE TABLE abc(a, b, c) } db eval { INSERT INTO abc VALUES(1, 2, 3); } } {} |
︙ | ︙ |
Changes to test/quick.test.
1 2 3 4 5 6 7 8 | # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # # $Id: quick.test,v 1.84 2008/06/26 08:29:35 danielk1977 Exp $ proc lshift {lvar} { upvar $lvar l set ret [lindex $l 0] set l [lrange $l 1 end] return $ret } |
︙ | ︙ | |||
38 39 40 41 42 43 44 45 46 47 48 49 50 51 | proc finish_test {} {} set ISQUICK 1 set EXCLUDE { all.test async.test async2.test corrupt.test crash.test crash2.test crash3.test crash4.test crash5.test crash6.test | > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | proc finish_test {} {} set ISQUICK 1 set EXCLUDE { all.test async.test async2.test async3.test corrupt.test crash.test crash2.test crash3.test crash4.test crash5.test crash6.test |
︙ | ︙ |