1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

keyboxd: Timeout on failure to get the database lock.

* kbx/backend-sqlite.c (dblock_info_cb): New.
(create_or_open_database): Add arg ctrl.  Add a 10 second timeout.
Avoid warning on error if not locked.
(be_sqlite_add_resource): Do not open the database here.
(be_sqlite_search): ... but do it here.
--

Note that we need to delay the initalization to the first use of the
database so that we actually have a recipient for the status messages.

GnuPG-bug-id: 6838
This commit is contained in:
Werner Koch 2023-12-18 15:25:45 +01:00
parent 937aeb1904
commit c99282fc78
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -521,11 +521,45 @@ run_sql_statement (const char *sqlstr)
} }
static int
dblock_info_cb (dotlock_t h, void *opaque, enum dotlock_reasons reason,
const char *format, ...)
{
ctrl_t ctrl = opaque;
va_list arg_ptr;
gpg_error_t err;
int rc = 0;
char tmpbuf[200];
(void)h;
if (reason == DOTLOCK_WAITING)
{
if (format)
{
va_start (arg_ptr, format);
gpgrt_vsnprintf (tmpbuf, sizeof tmpbuf, format, arg_ptr);
va_end (arg_ptr);
}
else
*tmpbuf = 0;
err = kbxd_status_printf (ctrl, "NOTE", "database_open %u %s",
gpg_error (GPG_ERR_LOCKED), tmpbuf);
if (err)
{
log_error ("sending status line failed: %s\n", gpg_strerror (err));
rc = 1; /* snprintf failed. */
}
}
return rc;
}
/* Create and initialize a new SQL database file if it does not /* Create and initialize a new SQL database file if it does not
* exists; else open it and check that all required objects are * exists; else open it and check that all required objects are
* available. */ * available. */
static gpg_error_t static gpg_error_t
create_or_open_database (const char *filename) create_or_open_database (ctrl_t ctrl, const char *filename)
{ {
gpg_error_t err; gpg_error_t err;
int res; int res;
@ -542,7 +576,16 @@ create_or_open_database (const char *filename)
/* To avoid races with other temporary instances of keyboxd trying /* To avoid races with other temporary instances of keyboxd trying
* to create or update the database, we run the database with a lock * to create or update the database, we run the database with a lock
* file held. */ * file held. */
database_lock = dotlock_create (filename, 0); database_lock = dotlock_create (filename, DOTLOCK_PREPARE_CREATE);
if (!database_lock)
{
err = gpg_error_from_syserror ();
if (opt.verbose)
log_info ("can't allocate dotlock handle: %s\n", gpg_strerror (err));
goto leave;
}
dotlock_set_info_cb (database_lock, dblock_info_cb, ctrl);
database_lock = dotlock_finish_create (database_lock, filename);
if (!database_lock) if (!database_lock)
{ {
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
@ -556,7 +599,7 @@ create_or_open_database (const char *filename)
goto leave; goto leave;
} }
if (dotlock_take (database_lock, -1)) if (dotlock_take (database_lock, 10000))
{ {
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
/* This is something bad. Probably a stale lockfile. */ /* This is something bad. Probably a stale lockfile. */
@ -646,6 +689,7 @@ create_or_open_database (const char *filename)
{ {
log_error (_("error creating database '%s': %s\n"), log_error (_("error creating database '%s': %s\n"),
filename, gpg_strerror (err)); filename, gpg_strerror (err));
if (dotlock_is_locked (database_lock))
dotlock_release (database_lock); dotlock_release (database_lock);
dotlock_destroy (database_lock); dotlock_destroy (database_lock);
database_lock = NULL; database_lock = NULL;
@ -660,7 +704,6 @@ gpg_error_t
be_sqlite_add_resource (ctrl_t ctrl, backend_handle_t *r_hd, be_sqlite_add_resource (ctrl_t ctrl, backend_handle_t *r_hd,
const char *filename, int readonly) const char *filename, int readonly)
{ {
gpg_error_t err;
backend_handle_t hd; backend_handle_t hd;
(void)ctrl; (void)ctrl;
@ -672,19 +715,10 @@ be_sqlite_add_resource (ctrl_t ctrl, backend_handle_t *r_hd,
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
hd->db_type = DB_TYPE_SQLITE; hd->db_type = DB_TYPE_SQLITE;
strcpy (hd->filename, filename); strcpy (hd->filename, filename);
err = create_or_open_database (filename);
if (err)
goto leave;
hd->backend_id = be_new_backend_id (); hd->backend_id = be_new_backend_id ();
*r_hd = hd; *r_hd = hd;
hd = NULL; return 0;
leave:
xfree (hd);
return err;
} }
@ -1139,6 +1173,10 @@ be_sqlite_search (ctrl_t ctrl,
log_assert (backend_hd && backend_hd->db_type == DB_TYPE_SQLITE); log_assert (backend_hd && backend_hd->db_type == DB_TYPE_SQLITE);
log_assert (request); log_assert (request);
err = create_or_open_database (ctrl, backend_hd->filename);
if (err)
return err;
acquire_mutex (); acquire_mutex ();
/* Find the specific request part or allocate it. */ /* Find the specific request part or allocate it. */