Friday, September 7, 2012

CORE-3740 and Firebird V2.5.2


CORE-3740 - SELECT using IN list with 153 or more elements causes crash.
This problem only occurs on MacOS, and cannot be reproduced on Linux or Windows. Initial analysis showed that adjusting the optimisation level of the code as it links (O1 instead of O3) would increase the number of INS that could be supported but you would still get a crash eventually if the number of INS was large enough.
The consensus of opinion was that this was a stack issue, so we increased the stack from the default 8mb in launchctl to 64mb, our test still crashed.

We then tried embedded (local) firebird and increased the cache there using ulimit, strangely enough this worked. So it definitely was a stack issue but where? Some debugging code and some careful googling showed the problem. Even Classic launches a forked inet_server via a new thread.

From an Apple Technical Q&A
"Each Mac OS X process is launched with a default stack size of 8 Megabytes. This allocation is used exclusively for the main thread's stack needs. Each subsequent thread created is allocated its own default stack, the size of which differs depending on the threading API used. For example, the Mac OS X implementation of Pthreads defines a default stack size of 512 Kilobytes, while Carbon MPTasks are created with a 4 Kilobyte stack."

Patch applied to src/jrd/ThreadStart.cpp

-#ifdef _AIX
-// adjust stack size for AIX
+#if defined(_AIX) || defined(DARWIN)
+// adjust stack size

 // For AIX 32-bit compiled applications, the default stacksize is 96 KB,
 // see . For 64-bit compiled applications, the default stacksize
 // is 192 KB. This is too small - see HP-UX note above

+// For MacOS default stack is 512 KB, which is also too small in 2012.
+
     size_t stack_size;
     state = pthread_attr_getstacksize(&pattr, &stack_size);
     if (state)
         Firebird::system_call_failed::raise("pthread_attr_getstacksize");

-    if (stack_size < 0x40000L)
+    if (stack_size < 0x400000L)
     {
-        state = pthread_attr_setstacksize(&pattr, 0x40000L);
+        state = pthread_attr_setstacksize(&pattr, 0x400000L);
         if (state)
             Firebird::system_call_failed::raise("pthread_attr_setstacksize", state);

No comments: