Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Disable automatic invocation of sqlite3_release_memory() when a malloc() fails in those cases where the global mutex is held. (CVS 2860) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
6fdbb8b771e490f0d791326689245302 |
User & Date: | danielk1977 2006-01-05 13:48:29.000 |
Context
2006-01-05
| ||
14:22 | Fix for ticket #1582 (Double delete of invalid LIMIT clause Expr* applied to a UNION ALL query). (CVS 2861) (check-in: 5dec3a392b user: danielk1977 tags: trunk) | |
13:48 | Disable automatic invocation of sqlite3_release_memory() when a malloc() fails in those cases where the global mutex is held. (CVS 2860) (check-in: 6fdbb8b771 user: danielk1977 tags: trunk) | |
11:34 | Add the shared schema/pager modifications. Very few tests so far. (CVS 2859) (check-in: deeda0dc06 user: danielk1977 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.315 2006/01/05 13:48:29 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
︙ | ︙ | |||
207 208 209 210 211 212 213 | sqlite3HashClear(&db->aFunc); sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ if( db->pErr ){ sqlite3ValueFree(db->pErr); } | < < < < < < < < < < < < < < < < < < < < | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | sqlite3HashClear(&db->aFunc); sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ if( db->pErr ){ sqlite3ValueFree(db->pErr); } db->magic = SQLITE_MAGIC_ERROR; sqliteFree(db->aDb[1].pSchema); sqliteFree(db); sqlite3MallocAllow(); return SQLITE_OK; } |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | ){ int rc; struct lockKey key1; struct openKey key2; struct stat statbuf; struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; #ifdef SQLITE_UNIX_THREADS if( threadsOverrideEachOthersLocks<0 ){ testThreadLockingBehavior(fd); } key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); #endif memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); if( pLock==0 ){ struct lockInfo *pOld; pLock = sqliteMallocRaw( sizeof(*pLock) ); | > > > > > > | > > > | > | > | > > > > > | | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | ){ int rc; struct lockKey key1; struct openKey key2; struct stat statbuf; struct lockInfo *pLock; struct openCnt *pOpen; SqliteTsd *pTsd = sqlite3Tsd(); rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; /* Disable the sqlite3_release_memory() function */ assert( !pTsd->disableReleaseMemory ); pTsd->disableReleaseMemory = 1; memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; #ifdef SQLITE_UNIX_THREADS if( threadsOverrideEachOthersLocks<0 ){ testThreadLockingBehavior(fd); } key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); #endif memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); if( pLock==0 ){ struct lockInfo *pOld; pLock = sqliteMallocRaw( sizeof(*pLock) ); if( pLock==0 ){ rc = 1; goto exit_findlockinfo; } pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; pLock->locktype = 0; pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); if( pOld!=0 ){ assert( pOld==pLock ); sqliteFree(pLock); rc = 1; goto exit_findlockinfo; } }else{ pLock->nRef++; } *ppLock = pLock; pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ struct openCnt *pOld; pOpen = sqliteMallocRaw( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); rc = 1; goto exit_findlockinfo; } pOpen->key = key2; pOpen->nRef = 1; pOpen->nLock = 0; pOpen->nPending = 0; pOpen->aPending = 0; pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); if( pOld!=0 ){ assert( pOld==pOpen ); sqliteFree(pOpen); releaseLockInfo(pLock); rc = 1; goto exit_findlockinfo; } }else{ pOpen->nRef++; } *ppOpen = pOpen; exit_findlockinfo: /* Re-enable sqlite3_release_memory() */ pTsd->disableReleaseMemory = 0; return rc; } /* ** Delete the named file */ static int unixDelete(const char *zFilename){ unlink(zFilename); |
︙ | ︙ | |||
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 | return rc; } /* ** Close a file. */ static int unixClose(OsFile **pId){ unixFile *id = (unixFile*)*pId; if( !id ) return SQLITE_OK; if( CHECK_THREADID(id) ) return SQLITE_MISUSE; unixUnlock(*pId, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3Os.xEnterMutex(); if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; | > > > > > > | 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 | return rc; } /* ** Close a file. */ static int unixClose(OsFile **pId){ SqliteTsd *pTsd = sqlite3Tsd(); unixFile *id = (unixFile*)*pId; if( !id ) return SQLITE_OK; if( CHECK_THREADID(id) ) return SQLITE_MISUSE; unixUnlock(*pId, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3Os.xEnterMutex(); /* Disable the sqlite3_release_memory() function */ assert( !pTsd->disableReleaseMemory ); pTsd->disableReleaseMemory = 1; if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; |
︙ | ︙ | |||
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 | } }else{ /* There are no outstanding locks so we can close the file immediately */ close(id->h); } releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); sqlite3Os.xLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqliteFree(id); *pId = 0; return SQLITE_OK; | > > > > | 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 | } }else{ /* There are no outstanding locks so we can close the file immediately */ close(id->h); } releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); /* Disable the sqlite3_release_memory() function */ pTsd->disableReleaseMemory = 0; sqlite3Os.xLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqliteFree(id); *pId = 0; return SQLITE_OK; |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.230 2006/01/05 13:48:29 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 | */ #ifndef SQLITE_OMIT_MEMORY_MANAGEMENT int sqlite3pager_release_memory(int nReq){ SqliteTsd *pTsd = sqlite3Tsd(); Pager *p; int nReleased = 0; int i; /* Outermost loop runs for at most two iterations. First iteration we ** try to find memory that can be released without calling fsync(). Second ** iteration (which only runs if the first failed to free nReq bytes of ** memory) is permitted to call fsync(). This is of course much more ** expensive. */ | > > > > > > > > > > | 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 | */ #ifndef SQLITE_OMIT_MEMORY_MANAGEMENT int sqlite3pager_release_memory(int nReq){ SqliteTsd *pTsd = sqlite3Tsd(); Pager *p; int nReleased = 0; int i; /* If the disableReleaseMemory memory flag is set, this operation is ** a no-op; zero bytes of memory are freed. The flag is set before ** malloc() is called while the global mutex (see sqlite3Os.xEnterMutex) ** is held. Because some of the code invoked by this function may also ** try to obtain the mutex, proceding may cause a deadlock. */ if( pTsd->disableReleaseMemory ){ return 0; } /* Outermost loop runs for at most two iterations. First iteration we ** try to find memory that can be released without calling fsync(). Second ** iteration (which only runs if the first failed to free nReq bytes of ** memory) is permitted to call fsync(). This is of course much more ** expensive. */ |
︙ | ︙ |
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.449 2006/01/05 13:48:29 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Many people are failing to set -DNDEBUG=1 when compiling SQLite. ** Setting NDEBUG makes the code smaller and run faster. So the following |
︙ | ︙ | |||
278 279 280 281 282 283 284 285 286 287 288 289 290 291 | /* ** An instance of this structure is allocated for each thread that uses SQLite. */ struct SqliteTsd { u8 isInit; /* True if structure has been initialised */ u8 mallocFailed; /* True after a malloc() has failed */ #ifndef SQLITE_OMIT_MEMORY_MANAGEMENT i64 nSoftHeapLimit; /* -ve for unlimited */ i64 nAlloc; /* Number of bytes currently allocated */ Pager *pPager; /* Linked list of all pagers in this thread */ #endif | > | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | /* ** An instance of this structure is allocated for each thread that uses SQLite. */ struct SqliteTsd { u8 isInit; /* True if structure has been initialised */ u8 mallocFailed; /* True after a malloc() has failed */ u8 disableReleaseMemory; /* True to make sqlite3_release_memory() a no-op */ #ifndef SQLITE_OMIT_MEMORY_MANAGEMENT i64 nSoftHeapLimit; /* -ve for unlimited */ i64 nAlloc; /* Number of bytes currently allocated */ Pager *pPager; /* Linked list of all pagers in this thread */ #endif |
︙ | ︙ |
Changes to test/all.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # 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. # #*********************************************************************** # This file runs all tests. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 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. # #*********************************************************************** # This file runs all tests. # # $Id: all.test,v 1.33 2006/01/05 13:48:29 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl rename finish_test really_finish_test proc finish_test {} {memleak_check} if {[file exists ./sqlite_test_count]} { |
︙ | ︙ | |||
52 53 54 55 56 57 58 | async.test crash.test autovacuum_crash.test quick.test malloc.test misuse.test memleak.test | < < < < < | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | async.test crash.test autovacuum_crash.test quick.test malloc.test misuse.test memleak.test } # Test files btree2.test and btree4.test don't work if the # SQLITE_DEFAULT_AUTOVACUUM macro is defined to true (because they depend # on tables being allocated starting at page 2). # ifcapable default_autovacuum { |
︙ | ︙ |