Регистрация обратного вызова для обработки ошибок SQLITE_BUSY
int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
Процедура sqlite3_busy_handler(D,X,P) устанавливает функцию обратного вызова X, которая может быть вызвана с аргументом P всякий раз, когда попытка доступа к таблице базы данных, связанной с соединением с базой данных D, производится другим потоком или процессом, который заблокировал таблицу. Интерфейс sqlite3_busy_handler() используется для реализации sqlite3_busy_timeout() и PRAGMA busy_timeout.
Если функция обратного вызова busy равна NULL, то SQLITE_BUSY возвращается немедленно при обнаружении блокировки. Если функция обратного вызова busy не равна NULL, то она может быть вызвана с двумя аргументами.
Первый аргумент функции обратного вызова busy — это копия указателя void*, который является третьим аргументом для sqlite3_busy_handler(). Второй аргумент — это количество вызовов функции обратного вызова busy ранее для того же события блокировки. Если функция обратного вызова busy возвращает 0, то дальнейшие попытки доступа к базе данных не предпринимаются, и SQLITE_BUSY возвращается приложению. Если функция обратного вызова возвращает ненулевое значение, то делается еще одна попытка доступа к базе данных, и цикл повторяется.
Наличие функции обратного вызова busy не гарантирует, что она будет вызвана при возникновении конфликта блокировки. Если SQLite определит, что вызов функции обратного вызова busy может привести к тупиковой ситуации, то она сразу вернет SQLITE_BUSY приложению вместо вызова функции обратного вызова. Рассмотрим ситуацию, когда один процесс держит блокировку чтения, которую он пытается повысить до блокировки резервирования, а второй процесс держит блокировку резервирования, которую он пытается повысить до эксклюзивной блокировки. Первый процесс не может продолжить, потому что заблокирован вторым, а второй процесс не может продолжить, потому что заблокирован первым. Если обе функции обратного вызова busy вызываются, ни один из процессов не сможет продвинуться вперед. Поэтому SQLite возвращает SQLITE_BUSY для первого процесса, надеясь, что это заставит первый процесс освободить блокировку чтения и позволит второму процессу продолжить.
По умолчанию функция обратного вызова busy равна NULL.
Для каждого соединения с базой данных может быть определена только одна функция обратного вызова busy. Установка новой функции обратного вызова очищает любую ранее установленную функцию. Обратите внимание, что вызов sqlite3_busy_timeout() или вычисление PRAGMA busy_timeout=N изменит функцию обратного вызова busy и, следовательно, очистит любую ранее установленную функцию.
Функция обратного вызова busy не должна выполнять никаких действий, которые изменяют соединение с базой данных, вызвавшее функцию обратного вызова busy. Другими словами, функция обратного вызова busy не является рекурсивной. Любые такие действия приводят к неопределенному поведению.
Функция обратного вызова busy не должна закрывать соединение с базой данных или подготовленное выражение, вызвавшее функцию обратного вызова busy.
См. также списки объектов, констант и функций.
SQLite is in the Public Domain.
https://sqlite.org/c3ref/busy_handler.html