OLD | NEW |
1 /* | 1 /* |
2 ** 2001 September 15 | 2 ** 2001 September 15 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 if( mem0.alarmThreshold<=0 ) return; | 210 if( mem0.alarmThreshold<=0 ) return; |
211 sqlite3_mutex_leave(mem0.mutex); | 211 sqlite3_mutex_leave(mem0.mutex); |
212 sqlite3_release_memory(nByte); | 212 sqlite3_release_memory(nByte); |
213 sqlite3_mutex_enter(mem0.mutex); | 213 sqlite3_mutex_enter(mem0.mutex); |
214 } | 214 } |
215 | 215 |
216 /* | 216 /* |
217 ** Do a memory allocation with statistics and alarms. Assume the | 217 ** Do a memory allocation with statistics and alarms. Assume the |
218 ** lock is already held. | 218 ** lock is already held. |
219 */ | 219 */ |
220 static int mallocWithAlarm(int n, void **pp){ | 220 static void mallocWithAlarm(int n, void **pp){ |
| 221 void *p; |
221 int nFull; | 222 int nFull; |
222 void *p; | |
223 assert( sqlite3_mutex_held(mem0.mutex) ); | 223 assert( sqlite3_mutex_held(mem0.mutex) ); |
| 224 assert( n>0 ); |
| 225 |
| 226 /* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal |
| 227 ** implementation of malloc_good_size(), which must be called in debug |
| 228 ** mode and specifically when the DMD "Dark Matter Detector" is enabled |
| 229 ** or else a crash results. Hence, do not attempt to optimize out the |
| 230 ** following xRoundup() call. */ |
224 nFull = sqlite3GlobalConfig.m.xRoundup(n); | 231 nFull = sqlite3GlobalConfig.m.xRoundup(n); |
| 232 |
225 sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n); | 233 sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n); |
226 if( mem0.alarmThreshold>0 ){ | 234 if( mem0.alarmThreshold>0 ){ |
227 sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); | 235 sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); |
228 if( nUsed >= mem0.alarmThreshold - nFull ){ | 236 if( nUsed >= mem0.alarmThreshold - nFull ){ |
229 mem0.nearlyFull = 1; | 237 mem0.nearlyFull = 1; |
230 sqlite3MallocAlarm(nFull); | 238 sqlite3MallocAlarm(nFull); |
231 }else{ | 239 }else{ |
232 mem0.nearlyFull = 0; | 240 mem0.nearlyFull = 0; |
233 } | 241 } |
234 } | 242 } |
235 p = sqlite3GlobalConfig.m.xMalloc(nFull); | 243 p = sqlite3GlobalConfig.m.xMalloc(nFull); |
236 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | 244 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
237 if( p==0 && mem0.alarmThreshold>0 ){ | 245 if( p==0 && mem0.alarmThreshold>0 ){ |
238 sqlite3MallocAlarm(nFull); | 246 sqlite3MallocAlarm(nFull); |
239 p = sqlite3GlobalConfig.m.xMalloc(nFull); | 247 p = sqlite3GlobalConfig.m.xMalloc(nFull); |
240 } | 248 } |
241 #endif | 249 #endif |
242 if( p ){ | 250 if( p ){ |
243 nFull = sqlite3MallocSize(p); | 251 nFull = sqlite3MallocSize(p); |
244 sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull); | 252 sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull); |
245 sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); | 253 sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); |
246 } | 254 } |
247 *pp = p; | 255 *pp = p; |
248 return nFull; | |
249 } | 256 } |
250 | 257 |
251 /* | 258 /* |
252 ** Allocate memory. This routine is like sqlite3_malloc() except that it | 259 ** Allocate memory. This routine is like sqlite3_malloc() except that it |
253 ** assumes the memory subsystem has already been initialized. | 260 ** assumes the memory subsystem has already been initialized. |
254 */ | 261 */ |
255 void *sqlite3Malloc(u64 n){ | 262 void *sqlite3Malloc(u64 n){ |
256 void *p; | 263 void *p; |
257 if( n==0 || n>=0x7fffff00 ){ | 264 if( n==0 || n>=0x7fffff00 ){ |
258 /* A memory allocation of a number of bytes which is near the maximum | 265 /* A memory allocation of a number of bytes which is near the maximum |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second | 519 /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second |
513 ** argument to xRealloc is always a value returned by a prior call to | 520 ** argument to xRealloc is always a value returned by a prior call to |
514 ** xRoundup. */ | 521 ** xRoundup. */ |
515 nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); | 522 nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); |
516 if( nOld==nNew ){ | 523 if( nOld==nNew ){ |
517 pNew = pOld; | 524 pNew = pOld; |
518 }else if( sqlite3GlobalConfig.bMemstat ){ | 525 }else if( sqlite3GlobalConfig.bMemstat ){ |
519 sqlite3_mutex_enter(mem0.mutex); | 526 sqlite3_mutex_enter(mem0.mutex); |
520 sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); | 527 sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); |
521 nDiff = nNew - nOld; | 528 nDiff = nNew - nOld; |
522 if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= | 529 if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= |
523 mem0.alarmThreshold-nDiff ){ | 530 mem0.alarmThreshold-nDiff ){ |
524 sqlite3MallocAlarm(nDiff); | 531 sqlite3MallocAlarm(nDiff); |
525 } | 532 } |
526 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); | 533 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); |
527 if( pNew==0 && mem0.alarmThreshold>0 ){ | 534 if( pNew==0 && mem0.alarmThreshold>0 ){ |
528 sqlite3MallocAlarm((int)nBytes); | 535 sqlite3MallocAlarm((int)nBytes); |
529 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); | 536 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); |
530 } | 537 } |
531 if( pNew ){ | 538 if( pNew ){ |
532 nNew = sqlite3MallocSize(pNew); | 539 nNew = sqlite3MallocSize(pNew); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 memset(p, 0, (size_t)n); | 575 memset(p, 0, (size_t)n); |
569 } | 576 } |
570 return p; | 577 return p; |
571 } | 578 } |
572 | 579 |
573 /* | 580 /* |
574 ** Allocate and zero memory. If the allocation fails, make | 581 ** Allocate and zero memory. If the allocation fails, make |
575 ** the mallocFailed flag in the connection pointer. | 582 ** the mallocFailed flag in the connection pointer. |
576 */ | 583 */ |
577 void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ | 584 void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ |
578 void *p = sqlite3DbMallocRaw(db, n); | 585 void *p; |
579 if( p ){ | 586 testcase( db==0 ); |
580 memset(p, 0, (size_t)n); | 587 p = sqlite3DbMallocRaw(db, n); |
581 } | 588 if( p ) memset(p, 0, (size_t)n); |
| 589 return p; |
| 590 } |
| 591 |
| 592 |
| 593 /* Finish the work of sqlite3DbMallocRawNN for the unusual and |
| 594 ** slower case when the allocation cannot be fulfilled using lookaside. |
| 595 */ |
| 596 static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ |
| 597 void *p; |
| 598 assert( db!=0 ); |
| 599 p = sqlite3Malloc(n); |
| 600 if( !p ) sqlite3OomFault(db); |
| 601 sqlite3MemdebugSetType(p, |
| 602 (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); |
582 return p; | 603 return p; |
583 } | 604 } |
584 | 605 |
585 /* | 606 /* |
586 ** Allocate and zero memory. If the allocation fails, make | 607 ** Allocate memory, either lookaside (if possible) or heap. |
587 ** the mallocFailed flag in the connection pointer. | 608 ** If the allocation fails, set the mallocFailed flag in |
| 609 ** the connection pointer. |
588 ** | 610 ** |
589 ** If db!=0 and db->mallocFailed is true (indicating a prior malloc | 611 ** If db!=0 and db->mallocFailed is true (indicating a prior malloc |
590 ** failure on the same database connection) then always return 0. | 612 ** failure on the same database connection) then always return 0. |
591 ** Hence for a particular database connection, once malloc starts | 613 ** Hence for a particular database connection, once malloc starts |
592 ** failing, it fails consistently until mallocFailed is reset. | 614 ** failing, it fails consistently until mallocFailed is reset. |
593 ** This is an important assumption. There are many places in the | 615 ** This is an important assumption. There are many places in the |
594 ** code that do things like this: | 616 ** code that do things like this: |
595 ** | 617 ** |
596 ** int *a = (int*)sqlite3DbMallocRaw(db, 100); | 618 ** int *a = (int*)sqlite3DbMallocRaw(db, 100); |
597 ** int *b = (int*)sqlite3DbMallocRaw(db, 200); | 619 ** int *b = (int*)sqlite3DbMallocRaw(db, 200); |
598 ** if( b ) a[10] = 9; | 620 ** if( b ) a[10] = 9; |
599 ** | 621 ** |
600 ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed | 622 ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed |
601 ** that all prior mallocs (ex: "a") worked too. | 623 ** that all prior mallocs (ex: "a") worked too. |
| 624 ** |
| 625 ** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is |
| 626 ** not a NULL pointer. |
602 */ | 627 */ |
603 void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ | 628 void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ |
604 void *p; | 629 void *p; |
605 assert( db==0 || sqlite3_mutex_held(db->mutex) ); | 630 if( db ) return sqlite3DbMallocRawNN(db, n); |
606 assert( db==0 || db->pnBytesFreed==0 ); | 631 p = sqlite3Malloc(n); |
| 632 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 633 return p; |
| 634 } |
| 635 void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ |
607 #ifndef SQLITE_OMIT_LOOKASIDE | 636 #ifndef SQLITE_OMIT_LOOKASIDE |
608 if( db ){ | 637 LookasideSlot *pBuf; |
609 LookasideSlot *pBuf; | 638 assert( db!=0 ); |
610 if( db->mallocFailed ){ | 639 assert( sqlite3_mutex_held(db->mutex) ); |
611 return 0; | 640 assert( db->pnBytesFreed==0 ); |
| 641 if( db->lookaside.bDisable==0 ){ |
| 642 assert( db->mallocFailed==0 ); |
| 643 if( n>db->lookaside.sz ){ |
| 644 db->lookaside.anStat[1]++; |
| 645 }else if( (pBuf = db->lookaside.pFree)==0 ){ |
| 646 db->lookaside.anStat[2]++; |
| 647 }else{ |
| 648 db->lookaside.pFree = pBuf->pNext; |
| 649 db->lookaside.nOut++; |
| 650 db->lookaside.anStat[0]++; |
| 651 if( db->lookaside.nOut>db->lookaside.mxOut ){ |
| 652 db->lookaside.mxOut = db->lookaside.nOut; |
| 653 } |
| 654 return (void*)pBuf; |
612 } | 655 } |
613 if( db->lookaside.bEnabled ){ | 656 }else if( db->mallocFailed ){ |
614 if( n>db->lookaside.sz ){ | 657 return 0; |
615 db->lookaside.anStat[1]++; | |
616 }else if( (pBuf = db->lookaside.pFree)==0 ){ | |
617 db->lookaside.anStat[2]++; | |
618 }else{ | |
619 db->lookaside.pFree = pBuf->pNext; | |
620 db->lookaside.nOut++; | |
621 db->lookaside.anStat[0]++; | |
622 if( db->lookaside.nOut>db->lookaside.mxOut ){ | |
623 db->lookaside.mxOut = db->lookaside.nOut; | |
624 } | |
625 return (void*)pBuf; | |
626 } | |
627 } | |
628 } | 658 } |
629 #else | 659 #else |
630 if( db && db->mallocFailed ){ | 660 assert( db!=0 ); |
| 661 assert( sqlite3_mutex_held(db->mutex) ); |
| 662 assert( db->pnBytesFreed==0 ); |
| 663 if( db->mallocFailed ){ |
631 return 0; | 664 return 0; |
632 } | 665 } |
633 #endif | 666 #endif |
634 p = sqlite3Malloc(n); | 667 return dbMallocRawFinish(db, n); |
635 if( !p && db ){ | |
636 db->mallocFailed = 1; | |
637 } | |
638 sqlite3MemdebugSetType(p, | |
639 (db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); | |
640 return p; | |
641 } | 668 } |
642 | 669 |
| 670 /* Forward declaration */ |
| 671 static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n); |
| 672 |
643 /* | 673 /* |
644 ** Resize the block of memory pointed to by p to n bytes. If the | 674 ** Resize the block of memory pointed to by p to n bytes. If the |
645 ** resize fails, set the mallocFailed flag in the connection object. | 675 ** resize fails, set the mallocFailed flag in the connection object. |
646 */ | 676 */ |
647 void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ | 677 void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ |
| 678 assert( db!=0 ); |
| 679 if( p==0 ) return sqlite3DbMallocRawNN(db, n); |
| 680 assert( sqlite3_mutex_held(db->mutex) ); |
| 681 if( isLookaside(db,p) && n<=db->lookaside.sz ) return p; |
| 682 return dbReallocFinish(db, p, n); |
| 683 } |
| 684 static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ |
648 void *pNew = 0; | 685 void *pNew = 0; |
649 assert( db!=0 ); | 686 assert( db!=0 ); |
650 assert( sqlite3_mutex_held(db->mutex) ); | 687 assert( p!=0 ); |
651 if( db->mallocFailed==0 ){ | 688 if( db->mallocFailed==0 ){ |
652 if( p==0 ){ | |
653 return sqlite3DbMallocRaw(db, n); | |
654 } | |
655 if( isLookaside(db, p) ){ | 689 if( isLookaside(db, p) ){ |
656 if( n<=db->lookaside.sz ){ | 690 pNew = sqlite3DbMallocRawNN(db, n); |
657 return p; | |
658 } | |
659 pNew = sqlite3DbMallocRaw(db, n); | |
660 if( pNew ){ | 691 if( pNew ){ |
661 memcpy(pNew, p, db->lookaside.sz); | 692 memcpy(pNew, p, db->lookaside.sz); |
662 sqlite3DbFree(db, p); | 693 sqlite3DbFree(db, p); |
663 } | 694 } |
664 }else{ | 695 }else{ |
665 assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); | 696 assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
666 assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); | 697 assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
667 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); | 698 sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
668 pNew = sqlite3_realloc64(p, n); | 699 pNew = sqlite3_realloc64(p, n); |
669 if( !pNew ){ | 700 if( !pNew ){ |
670 db->mallocFailed = 1; | 701 sqlite3OomFault(db); |
671 } | 702 } |
672 sqlite3MemdebugSetType(pNew, | 703 sqlite3MemdebugSetType(pNew, |
673 (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); | 704 (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); |
674 } | 705 } |
675 } | 706 } |
676 return pNew; | 707 return pNew; |
677 } | 708 } |
678 | 709 |
679 /* | 710 /* |
680 ** Attempt to reallocate p. If the reallocation fails, then free p | 711 ** Attempt to reallocate p. If the reallocation fails, then free p |
681 ** and set the mallocFailed flag in the database connection. | 712 ** and set the mallocFailed flag in the database connection. |
682 */ | 713 */ |
683 void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){ | 714 void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){ |
(...skipping 11 matching lines...) Expand all Loading... |
695 ** is because when memory debugging is turned on, these two functions are | 726 ** is because when memory debugging is turned on, these two functions are |
696 ** called via macros that record the current file and line number in the | 727 ** called via macros that record the current file and line number in the |
697 ** ThreadData structure. | 728 ** ThreadData structure. |
698 */ | 729 */ |
699 char *sqlite3DbStrDup(sqlite3 *db, const char *z){ | 730 char *sqlite3DbStrDup(sqlite3 *db, const char *z){ |
700 char *zNew; | 731 char *zNew; |
701 size_t n; | 732 size_t n; |
702 if( z==0 ){ | 733 if( z==0 ){ |
703 return 0; | 734 return 0; |
704 } | 735 } |
705 n = sqlite3Strlen30(z) + 1; | 736 n = strlen(z) + 1; |
706 assert( (n&0x7fffffff)==n ); | 737 zNew = sqlite3DbMallocRaw(db, n); |
707 zNew = sqlite3DbMallocRaw(db, (int)n); | |
708 if( zNew ){ | 738 if( zNew ){ |
709 memcpy(zNew, z, n); | 739 memcpy(zNew, z, n); |
710 } | 740 } |
711 return zNew; | 741 return zNew; |
712 } | 742 } |
713 char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ | 743 char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ |
714 char *zNew; | 744 char *zNew; |
| 745 assert( db!=0 ); |
715 if( z==0 ){ | 746 if( z==0 ){ |
716 return 0; | 747 return 0; |
717 } | 748 } |
718 assert( (n&0x7fffffff)==n ); | 749 assert( (n&0x7fffffff)==n ); |
719 zNew = sqlite3DbMallocRaw(db, n+1); | 750 zNew = sqlite3DbMallocRawNN(db, n+1); |
720 if( zNew ){ | 751 if( zNew ){ |
721 memcpy(zNew, z, (size_t)n); | 752 memcpy(zNew, z, (size_t)n); |
722 zNew[n] = 0; | 753 zNew[n] = 0; |
723 } | 754 } |
724 return zNew; | 755 return zNew; |
725 } | 756 } |
726 | 757 |
727 /* | 758 /* |
728 ** Free any prior content in *pz and replace it with a copy of zNew. | 759 ** Free any prior content in *pz and replace it with a copy of zNew. |
729 */ | 760 */ |
730 void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ | 761 void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ |
731 sqlite3DbFree(db, *pz); | 762 sqlite3DbFree(db, *pz); |
732 *pz = sqlite3DbStrDup(db, zNew); | 763 *pz = sqlite3DbStrDup(db, zNew); |
733 } | 764 } |
734 | 765 |
735 /* | 766 /* |
| 767 ** Call this routine to record the fact that an OOM (out-of-memory) error |
| 768 ** has happened. This routine will set db->mallocFailed, and also |
| 769 ** temporarily disable the lookaside memory allocator and interrupt |
| 770 ** any running VDBEs. |
| 771 */ |
| 772 void sqlite3OomFault(sqlite3 *db){ |
| 773 if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ |
| 774 db->mallocFailed = 1; |
| 775 if( db->nVdbeExec>0 ){ |
| 776 db->u1.isInterrupted = 1; |
| 777 } |
| 778 db->lookaside.bDisable++; |
| 779 } |
| 780 } |
| 781 |
| 782 /* |
| 783 ** This routine reactivates the memory allocator and clears the |
| 784 ** db->mallocFailed flag as necessary. |
| 785 ** |
| 786 ** The memory allocator is not restarted if there are running |
| 787 ** VDBEs. |
| 788 */ |
| 789 void sqlite3OomClear(sqlite3 *db){ |
| 790 if( db->mallocFailed && db->nVdbeExec==0 ){ |
| 791 db->mallocFailed = 0; |
| 792 db->u1.isInterrupted = 0; |
| 793 assert( db->lookaside.bDisable>0 ); |
| 794 db->lookaside.bDisable--; |
| 795 } |
| 796 } |
| 797 |
| 798 /* |
736 ** Take actions at the end of an API call to indicate an OOM error | 799 ** Take actions at the end of an API call to indicate an OOM error |
737 */ | 800 */ |
738 static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ | 801 static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ |
739 db->mallocFailed = 0; | 802 sqlite3OomClear(db); |
740 sqlite3Error(db, SQLITE_NOMEM); | 803 sqlite3Error(db, SQLITE_NOMEM); |
741 return SQLITE_NOMEM; | 804 return SQLITE_NOMEM_BKPT; |
742 } | 805 } |
743 | 806 |
744 /* | 807 /* |
745 ** This function must be called before exiting any API function (i.e. | 808 ** This function must be called before exiting any API function (i.e. |
746 ** returning control to the user) that has called sqlite3_malloc or | 809 ** returning control to the user) that has called sqlite3_malloc or |
747 ** sqlite3_realloc. | 810 ** sqlite3_realloc. |
748 ** | 811 ** |
749 ** The returned value is normally a copy of the second argument to this | 812 ** The returned value is normally a copy of the second argument to this |
750 ** function. However, if a malloc() failure has occurred since the previous | 813 ** function. However, if a malloc() failure has occurred since the previous |
751 ** invocation SQLITE_NOMEM is returned instead. | 814 ** invocation SQLITE_NOMEM is returned instead. |
752 ** | 815 ** |
753 ** If an OOM as occurred, then the connection error-code (the value | 816 ** If an OOM as occurred, then the connection error-code (the value |
754 ** returned by sqlite3_errcode()) is set to SQLITE_NOMEM. | 817 ** returned by sqlite3_errcode()) is set to SQLITE_NOMEM. |
755 */ | 818 */ |
756 int sqlite3ApiExit(sqlite3* db, int rc){ | 819 int sqlite3ApiExit(sqlite3* db, int rc){ |
757 /* If the db handle must hold the connection handle mutex here. | 820 /* If the db handle must hold the connection handle mutex here. |
758 ** Otherwise the read (and possible write) of db->mallocFailed | 821 ** Otherwise the read (and possible write) of db->mallocFailed |
759 ** is unsafe, as is the call to sqlite3Error(). | 822 ** is unsafe, as is the call to sqlite3Error(). |
760 */ | 823 */ |
761 assert( db!=0 ); | 824 assert( db!=0 ); |
762 assert( sqlite3_mutex_held(db->mutex) ); | 825 assert( sqlite3_mutex_held(db->mutex) ); |
763 if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ | 826 if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ |
764 return apiOomError(db); | 827 return apiOomError(db); |
765 } | 828 } |
766 return rc & db->errMask; | 829 return rc & db->errMask; |
767 } | 830 } |
OLD | NEW |