Hi,
If I send signals to a process that is running an sqlite query on a DB in WAL
mode I get an SQLITE_BUSY error.
I did set a busy handler, and the timeout hasn't elapsed yet, so it appears
that EINTR is treated as an error and not retried, although
I haven't tracked down exactly where. I noticed that unixFileLock doesn't
handle EINTR though.
Testcase for SQLite 3.8.2 on Linux amd64:
$ gcc eintr.c -lsqlite3 -o eintr && ./eintr
Query 'INSERT INTO tbl(x) VALUES(3)' failed: database is locked [after 0.025
sec]
^^^ expected to see >20s here.
#include <stdio.h>
#include <sqlite3.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/signal.h>
static int run(sqlite3 *db, const char *sql)
{
struct timeval tv0, tv1;
char *errmsg = NULL;
gettimeofday(&tv0, NULL);
/* should use prepared statements for speed, but this is just for a
testcase */
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg)) {
gettimeofday(&tv1, NULL);
double dt = tv1.tv_sec - tv0.tv_sec + (tv1.tv_usec -
tv0.tv_usec)/1000000.0;
fprintf(stderr,"Query '%s' failed: %s [after %.3f sec]\n", sql, errmsg,
dt);
sqlite3_free(errmsg);
return -1;
}
return 0;
}
static void handler(int sig)
{
}
int main(int argc, char *argv[])
{
sqlite3 *db = NULL;
char *errmsg = NULL;
int ret = 1;
pid_t parent, pid;
struct timeval tv0, tv1;
signal(SIGUSR2, handler);
parent = getpid();
pid = fork();
if (pid < 0) {
perror("fork failed");
return 2;
}
if (!pid) {
gettimeofday(&tv0, NULL);
/* child */
for(;;) {
/* if you comment out the kill() line, then the queries fail
showing >20s wait times */
kill(parent, SIGUSR2);
usleep(50);
gettimeofday(&tv1, NULL);
if ((tv1.tv_sec - tv0.tv_sec) * 1000 + (tv1.tv_usec -
tv0.tv_usec)/1000 > 5000)
break;
}
exit(0);
}
pid = fork();
do {
int i;
if (sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE, NULL)) {
fprintf(stderr,"failed to open DB: %s", sqlite3_errmsg(db));
break;
}
sqlite3_busy_timeout(db, 20000);
if (run(db, "CREATE TABLE IF NOT EXISTS tbl(x INTEGER)"))
break;
if (run(db, "PRAGMA journal_mode=WAL"))
break;
if (run(db, "PRAGMA synchronous=normal"))
break;
for (i=0;i<1000;i++) {
if (run(db, "INSERT INTO tbl(x) VALUES(3)"))
break;
if (run(db, "UPDATE tbl set x = x+1"))
break;
}
if (i == 1000)
ret = 0;
} while(0);
if (sqlite3_close(db)) {
fprintf(stderr,"Failed to close DB");
ret = 1;
}
return ret;
}
P.S: thank you for the quick fix for sqlite3_randomness!
_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users