SQLite Forum

Unhandled exception on server application
Login

Unhandled exception on server application

(1) By Steevis (steevis) on 2021-06-17 04:02:58 [link] [source]

Hi!

I'm creating my own server using by SQLite3. This is a simple program for the user authentication and blocking user when his paid time is over. At the beginning the server opens a tiny database contains some users data (function sqlite_open). At each client query the server does simple operations with the database like checking login/password or a counter decrement (function sqlite3_exec).

I'm using VDS with Windows Server 2012.

After some time (few minutes or few hours) the server crashes with a unhandled exception. I think exception is generated by SQLite. The server crashes even the only one user is connected.

I tried to catch the exception:

try { bResult = sqlite3_exec( gpSQL, sQuery, SQLCallBack, 0, &zErrMsg ) == 0; } catch (std::exception& ex) { wxMessageBox( ex.what()); }

But there is a strange situation. A message box shown after a long time after the query (may be few hours). The exception text was "Unknown exception".

I can't understand what's the trouble.

(2) By Warren Young (wyoung) on 2021-06-17 04:25:31 in reply to 1 [link] [source]

SQLite is pure C. It couldn’t throw a C++ exception if it wanted to.

(5) By Stephan Beal (stephan) on 2021-06-17 10:40:41 in reply to 2 [link] [source]

SQLite is pure C. It couldn’t throw a C++ exception if it wanted to.

Related: nor should a C++ application which implements callbacks for a pure C library ever allow a C++ exception to propagate from such a callback. That's a recipe for memory leaks and corruption in mixed C/C++ code.

Thus if SQLCallBack is capable of throwing:

try { bResult = sqlite3_exec( gpSQL, sQuery, SQLCallBack, 0, &zErrMsg ) == 0; } catch (std::exception& ex) { wxMessageBox( ex.what()); }

then its use here is fundamentally broken.

(7) By Steevis (steevis) on 2021-06-17 12:22:42 in reply to 5 [link] [source]

Hi, Stephan!

How do I correct use sqlite3_exec in my C++ program? There are no difference in examples :(

This is my callback function :

static int SQLCallBack( void *NotUsed, int argc, char **argv, char **azColName )
{
   // add results to global array
   int i;
   for(i = 0; i<argc; i++) {
      gaSQLResult.Add( argv[i] ? argv[i] : "NULL" );
   }
   return 0;
}

Thanks.

(8) By Stephan Beal (stephan) on 2021-06-17 12:35:43 in reply to 7 [link] [source]

How do I correct use sqlite3_exec in my C++ program?

If your callback is guaranteed to never throw an exception then it's fine as-is. i suspect, however, that:

gaSQLResult.Add( argv[i] ? argv[i] : "NULL" );

can potentially throw an exception, presumably a std::bad_alloc.

C libraries have no way of properly handling C++ exceptions which pass through them, so it's critical (for their proper behavior) that no C++ exceptions ever do so. If your callback has to throw an exception, catch it in that callback and return the relevant C-level result code. In the case of sqlite3_exec(), returning any non-0 value will cause sqlite3_exec() to fail properly:

https://www.sqlite.org/c3ref/exec.html

If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() routine returns SQLITE_ABORT without invoking the callback again and without running any subsequent SQL statements.

To protect against a leaking exception, wrap up the body of your function in a try/catch. If no exception is thrown, return 0, else return any non-0 value.

(10) By anonymous on 2021-06-17 15:55:53 in reply to 5 [link] [source]

ever allow a C++ exception to propagate

gcc 6.3 manual says -fexceptions allows "C code to interoperate with exception handlers written in C++". I suspect it allows an exception from C++ to pass through C code, and be caught in C++ code. Or am I misinterpreting ‘interoperate’ here?

(11) By Stephan Beal (stephan) on 2021-06-17 16:38:05 in reply to 10 [link] [source]

gcc 6.3 manual says -fexceptions allows "C code to interoperate with exception handlers written in C++".

That's a compiler-specific extension. Portable code never relies on such things.

(12) By anonymous on 2021-06-17 18:18:29 in reply to 11 [link] [source]

While I am not familiar with OP’s compiler options I presume something equivalent to -fexceptions might be supported. If it’s a exception propagation issue through C code, compiling the SQLite code with that compiler option might help resolve it.

I did not see OP mention about writing portable code. Is writing portable code even a feasible requirement for most software projects?

(13) By Warren Young (wyoung) on 2021-06-17 19:02:40 in reply to 12 [link] [source]

compiling the SQLite code with that compiler option might help resolve it.

Are you certain that works through a C function pointer? I can see how GCC might unwind a regular C function call while processing a thrown C++ exception, but as loosey-goosey as C treats pointers, I wouldn't bet on it happening in this case.

Is writing portable code even a feasible requirement for most software projects?

I understand your point, but once you go wandering down into UB land, you can't expect a SAR party organized on the SQLite forum to do much more than call out, "Please return to the well-lit path!"

Anyway, wxWidgets on a 9-year-old OS that's been out of mainstream support for 3 years now? And using the obsolete VDS API atop that, without any explanation of what that might have to do with the reported problem? The OP shows many signs of doing questionable things, so it's fair to question whether he's taken care of UB-ish things.

(3) By anonymous on 2021-06-17 04:50:27 in reply to 1 [link] [source]

Maybe gpSQL is nullptr or already free()-ed, so it just segfaults.

(4) By Steevis (steevis) on 2021-06-17 07:57:06 in reply to 1 [link] [source]

No, gpSQL is not null.

Maybe I must open and close the database at each client query?

(6.1) By Simon Slavin (slavin) on 2021-06-17 12:20:22 edited from 6.0 in reply to 4 [link] [source]

There is nothing in SQLite that requires that. If you're using something that requires opening and closing the database at each query, something is wrong with the programming language you're using, the shim between that language and SQLite, or your code.

Opening and closing connections are slow operations. A single query executes quickly and a lot of effort went into optimizing the programming involved. A single program would normally open or close connections, so less effort has gone into making sure it happens as quickly as possible.

There are many meanings for 'VDS' and I think you'll do better asking experts on VDS than experts on SQLite. Perhaps you can find a forum where you can ask them your question. I'm especially wary of anything that returns 'Unknown exception'.

(9) By anonymous on 2021-06-17 14:03:47 in reply to 1 [link] [source]

It might be a good idea to attach a debugger to the server process and let it crash. If you've got crash dumps, load those in a debugger. Make sure to build your program with debugging symbols. Once you do that, you'll know where exactly the crash happens and might even get an idea on the reasons for the crash. It could be a heap corruption. DrMemory sometimes helps in debugging those on Windows.

(14) By Steevis (steevis) on 2021-06-18 03:07:12 in reply to 9 [link] [source]

I've installed MinGW on my remote VDS server and attached a debugger to the server process. The server crashed and GDB shown no error.
The most interesting that the unhandled exception was generated by a Visual C++ runtime library. But the server was written in MinGW.
Maybe the error occurs in the windows library like msvcrt.dll.
There was no error when I used a simple text file as a users db instead using SQLite.
I think somehow SQLite conflicts with Windows Server 2012 libraries on my VDS server.
Maybe it's all about a virtual machine on the VDS server?

(15) By Keith Medcalf (kmedcalf) on 2021-06-18 03:26:38 in reply to 14 [source]

What is a VDS? Venereal Disease Symptoms? Depending on the particular symptoms, penicillin may be curative.

You have provided insufficient information for meaningful diagnosis.

Note that many "virtualization emulators" do not actually provide the functional facilities required for SQLite3 to function correctly. Perhaps your VDS is defective as designed ...

(16) By Steevis (steevis) on 2021-06-18 04:07:03 in reply to 15 [link] [source]

VDS is virtual dedicated server.

(17) By Steevis (steevis) on 2021-06-18 05:05:03 in reply to 15 [link] [source]

Virtualization is KVM.

(22) By anonymous on 2021-06-19 08:28:58 in reply to 14 [link] [source]

This is better, but I'm afraid I still don't have a good answer to your problems. You still need to figure out how to debug your application. Perhaps Windows can be configured to leave memory dumps of your application somewhere for you to pick them apart in a debugger?

The server crashed and GDB shown no error

Please help us help you. How exactly you attach the debugger to the server application? What is the exact text of the error message? What exactly happens in GDB on application crash?

Maybe if you interrupt the application in GDB at the moment you see the error message, you might be able to obtain a backtrace. I don't know. Maybe if you try DrMemory, you'll get more informative results.

The most interesting that the unhandled exception was generated by a Visual C++ runtime library. But the server was written in MinGW.

This is normal. Applications compiled with MinGW link to msvcrt.dll.

There was no error when I used a simple text file as a users db instead using SQLite.

SQLite could be doing more heap allocations than a simple text file back-end, making the heap corruption symptoms present faster, but that's just symptoms, not the underlying problem. You could have a memory corruption error somewhere in the interface between SQLite and your application, or you could have it elsewhere. Maybe your application was just "lucky" enough to not have been affected by the memory corruption before you started using SQLite.

(18) By Keith Medcalf (kmedcalf) on 2021-06-18 06:40:02 in reply to 1 [link] [source]

What do you mean "a few hours" afterwards?

(19) By Steevis (steevis) on 2021-06-18 07:58:26 in reply to 18 [link] [source]

There is no certain time between the server starting and crash.
I run the server and client applications at the same time. The server works nice for a while. And after some time the exception appears.

(20) By Keith Medcalf (kmedcalf) on 2021-06-18 08:35:08 in reply to 19 [link] [source]

So you are saying that the particular line you are attributing this to (the sqlite3_exec) "works for a while" and then it does not?

(21) By Keith Medcalf (kmedcalf) on 2021-06-18 08:41:44 in reply to 19 [link] [source]

That would seem to indicate that each time on the merry-go-round you are consuming some resource and forgetting to release it.