Я выяснил где собака порылась. Виноват оказался MS.
В отладчике выяснилось, что APC вылетает из функции select, которую
использует внутри gds32.dll. Любой код вида
void APIENTRY user_apc(ULONG_PTR dwParam)
{
//1
}
void main()
{
QueueUserAPC(user_apc,GetCurrentThread(),0);
sql q("select 1 from rdb$database");
//любой sql-оператор на любых компонентах доступа
//2
}
Попадает в точку 1 перед точкой 2.
Причина этого описана в msdn:
-----------------------------------------------------------
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx
Note When issuing a blocking Winsock call such as select with the
timeout parameter set to NULL, Winsock may need to wait for a network
event before the call can complete. Winsock performs an alertable wait
in this situation, which can be interrupted by an asynchronous procedure
call (APC) scheduled on the same thread. Issuing another blocking
Winsock call inside an APC that interrupted an ongoing blocking Winsock
call on the same thread will lead to undefined behavior, and must never
be attempted by Winsock clients.
-----------------------------------------------------------
Печально всё это и лечению не подлежит. Даже если переделать gds32.dll
то редистрибьютить его нереально.