/ Check-in [5f6c06b9]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Must hold mutex on the destination during backups. Add documentation to warn programmers that attempting to use the destination connection during a backup can lead to deadlock. (CVS 6246)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5f6c06b974f26532264467ace603b6f1f830fba9
User & Date: drh 2009-02-03 21:13:08
Context
2009-02-03
22:17
A backup must clear the internal schema of the destination database so that the schema will be reloaded for the next sqlite3_prepare() (CVS 6247) check-in: 76f23a43 user: drh tags: trunk
21:13
Must hold mutex on the destination during backups. Add documentation to warn programmers that attempting to use the destination connection during a backup can lead to deadlock. (CVS 6246) check-in: 5f6c06b9 user: drh tags: trunk
19:55
Fixed postToParent() return type (Tcl_ThreadCreateType) in test_thread.c to compile with MSVC. Removed a few compiler warnings. Test harness change only. (CVS 6245) check-in: e9475aba user: shane tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/backup.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
122
123
124
125
126
127
128

129
130
131


132
133
134
135
136
137
138
...
244
245
246
247
248
249
250

251
252
253
254
255
256
257
...
399
400
401
402
403
404
405

406
407
408
409
410
411
412
...
416
417
418
419
420
421
422

423
424
425
426
427
428
429
...
435
436
437
438
439
440
441

442
443
444
445
446
447
448
...
552
553
554
555
556
557
558
559
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_backup_XXX() 
** API functions and the related features.
**
** $Id: backup.c,v 1.1 2009/02/03 16:51:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"

/* Macro to find the minimum of two numeric values.
*/
#ifndef MIN
................................................................................
  const char *zDestDb,                  /* Name of database within pDestDb */
  sqlite3* pSrcDb,                      /* Database connection to read from */
  const char *zSrcDb                    /* Name of database within pSrcDb */
){
  sqlite3_backup *p;                    /* Value to return */

  /* Lock the source database handle. The destination database

  ** handle is not locked. The user is required to ensure that no
  ** other thread accesses the destination handle for the duration
  ** of the backup operation.


  */
  sqlite3_mutex_enter(pSrcDb->mutex);

  if( pSrcDb==pDestDb ){
    sqlite3Error(
        pDestDb, SQLITE_ERROR, "Source and destination handles must be distinct"
    );
................................................................................
** Copy nPage pages from the source b-tree to the destination.
*/
int sqlite3_backup_step(sqlite3_backup *p, int nPage){
  int rc;

  sqlite3_mutex_enter(p->pSrcDb->mutex);
  sqlite3BtreeEnter(p->pSrc);


  rc = p->rc;
  if( rc==SQLITE_OK ){
    Pager * const pSrcPager = sqlite3BtreePager(p->pSrc);     /* Source pager */
    Pager * const pDestPager = sqlite3BtreePager(p->pDest);   /* Dest pager */
    int ii;                            /* Iterator variable */
    int nSrcPage;                      /* Size of source db in pages */
................................................................................
      assert( rc2==SQLITE_OK );
    }
  
    if( rc!=SQLITE_LOCKED && rc!=SQLITE_BUSY ){
      p->rc = rc;
    }
  }

  sqlite3BtreeLeave(p->pSrc);
  sqlite3_mutex_leave(p->pSrcDb->mutex);
  return rc;
}

/*
** Release all resources associated with an sqlite3_backup* handle.
................................................................................
  sqlite3_mutex *mutex;                /* Mutex to protect source database */
  int rc;                              /* Value to return */

  /* Enter the mutexes */
  sqlite3_mutex_enter(p->pSrcDb->mutex);
  sqlite3BtreeEnter(p->pSrc);
  mutex = p->pSrcDb->mutex;


  /* Detach this backup from the source pager. */
  if( p->pDestDb ){
    pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
    while( *pp!=p ){
      pp = &(*pp)->pNext;
    }
................................................................................
  sqlite3BtreeRollback(p->pDest);

  /* Set the error code of the destination database handle. */
  rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
  sqlite3Error(p->pDestDb, rc, 0);

  /* Exit the mutexes and free the backup context structure. */

  sqlite3BtreeLeave(p->pSrc);
  if( p->pDestDb ){
    sqlite3_free(p);
  }
  sqlite3_mutex_leave(mutex);
  return rc;
}
................................................................................
  }

  sqlite3BtreeLeave(pFrom);
  sqlite3BtreeLeave(pTo);
  return rc;
}
#endif /* SQLITE_OMIT_VACUUM */








|







 







>
|

|
>
>







 







>







 







>







 







>







 







>







 







<
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
...
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
...
559
560
561
562
563
564
565

**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_backup_XXX() 
** API functions and the related features.
**
** $Id: backup.c,v 1.2 2009/02/03 21:13:08 drh Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"

/* Macro to find the minimum of two numeric values.
*/
#ifndef MIN
................................................................................
  const char *zDestDb,                  /* Name of database within pDestDb */
  sqlite3* pSrcDb,                      /* Database connection to read from */
  const char *zSrcDb                    /* Name of database within pSrcDb */
){
  sqlite3_backup *p;                    /* Value to return */

  /* Lock the source database handle. The destination database
  ** handle is not locked in this routine, but it is locked in
  ** sqlite3_backup_step(). The user is required to ensure that no
  ** other thread accesses the destination handle for the duration
  ** of the backup operation.  Any attempt to use the destination
  ** database connection while a backup is in progress may cause
  ** a malfunction or a deadlock.
  */
  sqlite3_mutex_enter(pSrcDb->mutex);

  if( pSrcDb==pDestDb ){
    sqlite3Error(
        pDestDb, SQLITE_ERROR, "Source and destination handles must be distinct"
    );
................................................................................
** Copy nPage pages from the source b-tree to the destination.
*/
int sqlite3_backup_step(sqlite3_backup *p, int nPage){
  int rc;

  sqlite3_mutex_enter(p->pSrcDb->mutex);
  sqlite3BtreeEnter(p->pSrc);
  sqlite3_mutex_enter(p->pDestDb->mutex);

  rc = p->rc;
  if( rc==SQLITE_OK ){
    Pager * const pSrcPager = sqlite3BtreePager(p->pSrc);     /* Source pager */
    Pager * const pDestPager = sqlite3BtreePager(p->pDest);   /* Dest pager */
    int ii;                            /* Iterator variable */
    int nSrcPage;                      /* Size of source db in pages */
................................................................................
      assert( rc2==SQLITE_OK );
    }
  
    if( rc!=SQLITE_LOCKED && rc!=SQLITE_BUSY ){
      p->rc = rc;
    }
  }
  sqlite3_mutex_leave(p->pDestDb->mutex);
  sqlite3BtreeLeave(p->pSrc);
  sqlite3_mutex_leave(p->pSrcDb->mutex);
  return rc;
}

/*
** Release all resources associated with an sqlite3_backup* handle.
................................................................................
  sqlite3_mutex *mutex;                /* Mutex to protect source database */
  int rc;                              /* Value to return */

  /* Enter the mutexes */
  sqlite3_mutex_enter(p->pSrcDb->mutex);
  sqlite3BtreeEnter(p->pSrc);
  mutex = p->pSrcDb->mutex;
  sqlite3_mutex_enter(p->pDestDb->mutex);

  /* Detach this backup from the source pager. */
  if( p->pDestDb ){
    pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
    while( *pp!=p ){
      pp = &(*pp)->pNext;
    }
................................................................................
  sqlite3BtreeRollback(p->pDest);

  /* Set the error code of the destination database handle. */
  rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
  sqlite3Error(p->pDestDb, rc, 0);

  /* Exit the mutexes and free the backup context structure. */
  sqlite3_mutex_leave(p->pDestDb->mutex);
  sqlite3BtreeLeave(p->pSrc);
  if( p->pDestDb ){
    sqlite3_free(p);
  }
  sqlite3_mutex_leave(mutex);
  return rc;
}
................................................................................
  }

  sqlite3BtreeLeave(pFrom);
  sqlite3BtreeLeave(pTo);
  return rc;
}
#endif /* SQLITE_OMIT_VACUUM */

Changes to src/sqlite.h.in.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
6880
6881
6882
6883
6884
6885
6886
6887


6888
6889
6890
6891
6892
6893
6894
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.425 2009/02/03 18:47:23 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
**
** However, the application must guarantee that the destination database
** connection handle is not passed to any other API (by any thread) after 
** sqlite3_backup_init() is called and before the corresponding call to
** sqlite3_backup_finish(). Unfortunately SQLite does not currently check
** for this, if the application does use the destination [database connection]
** for some other purpose during a backup operation, things may appear to
** work correctly but in fact be subtly malfunctioning.


**
** Furthermore, if running in [shared cache mode], the application must
** guarantee that the shared cache used by the destination database
** is not accessed while the backup is running. In practice this means
** that the application must guarantee that the file-system file being 
** backed up to is not accessed by any connection within the process,
** not just the specific connection that was passed to sqlite3_backup_init().







|







 







|
>
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.426 2009/02/03 21:13:08 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
**
** However, the application must guarantee that the destination database
** connection handle is not passed to any other API (by any thread) after 
** sqlite3_backup_init() is called and before the corresponding call to
** sqlite3_backup_finish(). Unfortunately SQLite does not currently check
** for this, if the application does use the destination [database connection]
** for some other purpose during a backup operation, things may appear to
** work correctly but in fact be subtly malfunctioning.  Use of the
** destination database connection while a backup is in progress might
** also cause a mutex deadlock.
**
** Furthermore, if running in [shared cache mode], the application must
** guarantee that the shared cache used by the destination database
** is not accessed while the backup is running. In practice this means
** that the application must guarantee that the file-system file being 
** backed up to is not accessed by any connection within the process,
** not just the specific connection that was passed to sqlite3_backup_init().