core dump at _dl_sysinfo_int80 () - core

I have created a TCP client that connects to a listening server.
We implemeted TCP keep alive also.
Some times the client crashes and core dumped.
Below are the core dump traces.
Problem is in linux kernel version Update 4, kernel 2.6.9-42.0.10.
we had two core dumps.
(gdb) where
#0 0x005e77a2 in _dl_sysinfo_int80 () from /ddisk/d303/dumps/mhx239131/ld-
linux.so.2
#1 0x006c8bd1 in connect () from /ddisk/d303/dumps/mhx239131/libc.so.6
#2 0x08057863 in connect_to_host ()
#3 0x08052f38 in open_ldap_connection ()
#4 0x0805690a in new_connection ()
#5 0x08052cc9 in ldap_open ()
#6 0x080522cf in checkHosts ()
#7 0x08049b36 in pollLDEs ()
#8 0x0804d1cd in doOnChange ()
#9 0x0804a642 in main ()
(gdb) where
#0 0x005e77a2 in _dl_sysinfo_int80 () from /ddisk/d303/dumps/mhx239131/ld-
linux.so.2
#1 0x0068ab60 in __nanosleep_nocancel (
from /ddisk/d303/dumps/mhx239131/libc.so.6
#2 0x080520a2 in Sleep ()
#3 0x08049ac1 in pollLDEs ()
#4 0x0804d1cd in doOnChange ()
#5 0x0804a642 in main ()
We have tried to reproduce the problem in our environment, but we could not.
What would cause the core file?
Please help me to avoid such situation.
Thanks,
Naga

_dl_sysinfo_int80 is just a function which does a system call into the kernel. So the core dump is happening on a system call (probably the one used by connect in the first example and nanosleep in the second example), probably because you are passing invalid pointers.
The invalid pointers could be because the code which calls these functions being broken or because somewhere else in the program is broken and corrupting the program's memory.
Take a look at two frames above (frame #2) in the core dump for both examples and check the parameters being passed. Unfortunately, it seems you did not compile with debug information, making it harder to see them.
Additionally, I would suggest trying valgrind and seeing if it finds something.

Your program almost cetainly did not coredump in either of the above places.
Most likely, you either have multiple threads in your process (and some other thread caused the core dump), or something external caused your process to die (such as 'kill -SIGABRT <pid>').
If you do have multiple threads, GDB 'info threads' and 'thread apply all where' are likely to provide further clues.

Related

Unexplainable behaviour when integrating x86 FreeRTOS port (pthreads) and auxilary pthreads code

I am out of ideas of how to figure out where my problem is coming from.
I am trying to incorporate a Async UDP handler into an existing FreeRTOS emulator, both being pthreads based. The FreeRTOS implementation is essentially a wrapper around pthreads and the UDP handler spawns a FreeRTOS task which then spawns a pthread thread for each socket, such that the spawned threads can have their own sigaction to handle that specific UDP port with a specified callback.
As a sanity check I moved the UDP handler code into a stand alone build yesterday to test it and it works without fault, found here. All valgrind checks also showing no errors. The FreeRTOS Emulator is also stable when the UDP handler is not added, found here. The unstable integration can be found here.
Now when integrating the two I get behavior I have not been able to debug successfully yet. The bug presents itself as a heisenbug in that during debugging I am not able to recreate it always. All valgrind (memcheck, helgrind and drd) are not able to recreate the bug, only reporting errors in linked libraries such as SDL2, X11, mensa graphics etc. Post morten GDB is able to capture the fault as well as when using (gdb) set disable-randomization off.
The backtrace from gdb shows me the following
(gdb) bt
#0 0x00007faa2f45a41b in pthread_kill () from /usr/lib/libpthread.so.0
#1 0x0000564392f5c93b in prvResumeThread (xThreadId=0) at /home/alxhoff/git/GitHub/FreeRTOS-Emulator/lib/FreeRTOS_Kernel/portable/GCC/Posix/port.c:561
#2 0x0000564392f5c38b in vPortYield () at /home/alxhoff/git/GitHub/FreeRTOS-Emulator/lib/FreeRTOS_Kernel/portable/GCC/Posix/port.c:329
#3 0x0000564392f5d986 in xQueueGenericReceive (xQueue=0x564396692bd0, pvBuffer=0x0, xTicksToWait=4294967295, xJustPeeking=0) at /home/alxhoff/git/GitHub/FreeRTOS-Emulator/lib/FreeRTOS_Kernel/queue.c:1376
#4 0x0000564392f5b0d3 in vDemoTask1 (pvParameters=0x0) at /home/alxhoff/git/GitHub/FreeRTOS-Emulator/src/main.c:338
#5 0x0000564392f5c754 in prvWaitForStart (pvParams=0x5643966b2780) at /home/alxhoff/git/GitHub/FreeRTOS-Emulator/lib/FreeRTOS_Kernel/portable/GCC/Posix/port.c:496
#6 0x00007faa2f4524cf in start_thread () from /usr/lib/libpthread.so.0
#7 0x00007faa2efcd2d3 in clone () from /usr/lib/libc.so.6
The problem appears to be that prvResumeThread is not being passed a valid thread id as seen in #1. Going into the FreeRTOS sources I believe that this should not be the case as the same threads are created when the UDP handler and it's respective task are added, their addition somehow leads to FreeRTOS's pxCurrentTCB becoming invalid when executing xTaskGetCurrentTaskHandle which retrieves the thread handle for the faulting prvResumeThread call in #1 of the backtrace. Moving the task creation order around leads to the same error which makes me think I am dealing with some sort of memory leak but given that I cannot reproduce the error with valgrind I am unsure of how to diagnose the error.
I am worried this seems like a "debug my program" post but I am unsure of what methods or tools I can utilize to further my diagnosis, given my limited experience with multi-threaded debugging, and am in need of a push in the right direction.
Cheers

Qt multi-thread application freezes and several threads wait for the same mutex

I encountered a strange problem with my Qt-based multi-thread application. After several days running, the application will freeze without any response.
After freeze occurred, I can confirm that several threads, including the main thread, are in futex_wait_queue_me status. When I attach to that application to investigate thread status by GDB, the backtrace of those threads
shows that they all stopped at the following function with the same argument futex=0x45a2f8b8 <main_arena>.
__lll_lock_wait_private (futex=0x45a2f8b8 <main_arena>)
I know that on Linux, using non-asynchronous-safe functions within signal handlers is one of possible reasons for this status, i.e. several threads wait for the same mutex, (I can confirm from backtrace that they all stopped at malloc()/free() related function calls), but after I confirmed my Qt application, I can not find implementations related to Linux signal handlers. (but I am not sure whether Qt core library is using Linux signal handlers in its signal/slot mechanism.)
I am sorry that I can not provide source code for this question because it is a huge project. Would you like tell me some possible reasons for this phenomenon, or some advises on how to debug it?
Thanks in advance.
UPDATE 1:
I can provide backtrace, but sorry I have to delete some sensitive information.
Backtrace of sub thread:
#0 in __lll_lock_wait_private (futex=0x4ad078b8 <main_arena>)
#1 in __GI___libc_malloc (bytes=32) at malloc.c:2918
... ...
#11 in SystemEventImp::event(QEvent*) ()
#12 in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
#13 in QApplication::notify(QObject*, QEvent*) ()
#14 in QCoreApplication::notifyInternal(QObject*, QEvent*) ()
#15 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
#16 in QCoreApplication::sendPostedEvents (receiver=0x0, event_type=0) at kernel/qcoreapplication.cpp:1329
#17 in QWindowSystemInterface::sendWindowSystemEvents (flags=...) at kernel/qwindowsysteminterface.cpp:560
#18 in QUnixEventDispatcherQPA::processEvents (this=0x8079958, flags=...) at eventdispatchers/qunixeventdispatcher.cpp:70
#19 in QEventLoop::processEvents (this=0xbfffef50, flags=...) at kernel/qeventloop.cpp:136
#20 in QEventLoop::exec (this=0xbfffef50, flags=...) at kernel/qeventloop.cpp:212
#21 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1120
#22 in QGuiApplication::exec () at kernel/qguiapplication.cpp:1220
#23 in QApplication::exec () at kernel/qapplication.cpp:2689
#24 in main(argc=2, argv=0xbffff294)
Backtrace of main thread:
#0 in __lll_lock_wait_private (futex=0x4ad078b8 <main_arena>) at ../ports/sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.c:32
#1 in __GI___libc_malloc (bytes=8) at malloc.c:2918
... ...
#15 in QGraphicsView::paintEvent(QPaintEvent*) ()
#16 in QWidget::event(QEvent*) ()
#17 in QFrame::event(QEvent*) ()
#18 in QGraphicsView::viewportEvent(QEvent*) ()
#19 in Platform::Drawing::GraphicsView::viewportEvent(QEvent*) ()
#20 in QAbstractScrollAreaFilter::eventFilter(QObject*, QEvent*) ()
#21 in QCoreApplicationPrivate::cancel_handler(QObject*, QEvent*) ()
#22 in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
#23 in QApplication::notify(QObject*, QEvent*) ()
#24 in QCoreApplication::notifyInternal(QObject*, QEvent*) ()
#25 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) [clone .part.175] ()
#26 in QWidgetBackingStore::sync() ()
#27 in QWidgetPrivate::syncBackingStore() ()
#28 in QWidget::event(QEvent*) ()
#29 in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
#30 in QApplication::notify(QObject*, QEvent*) ()
#31 in QCoreApplication::notifyInternal(QObject*, QEvent*) ()
#32 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
#33 in QCoreApplication::sendPostedEvents (receiver=0x809ea50, event_type=77)
#34 in QGraphicsViewPrivate::dispatchPendingUpdateRequests (this=0x80e4418)
#35 in QGraphicsScenePrivate::_q_processDirtyItems (this=0x80de238) at graphicsview/qgraphicsscene.cpp:508
#36 in QGraphicsScene::qt_static_metacall (_o=0x80d1a80, _c=QMetaObject::InvokeMetaMethod, _id=15, _a=0x865e238)
#37 in QMetaCallEvent::placeMetaCall (this=0x898d020, object=0x80d1a80)
#38 in QObject::event (this=0x80d1a80, e=0x898d020) at kernel/qobject.cpp:1070
#39 in QGraphicsScene::event (this=0x80d1a80, event=0x898d020) at graphicsview/qgraphicsscene.cpp:3478
#40 in QApplicationPrivate::notify_helper (this=0x8077ba0, receiver=0x80d1a80, e=0x898d020) at kernel/qapplication.cpp:3457
#41 in QApplication::notify (this=0x8077970, receiver=0x80d1a80, e=0x898d020) at kernel/qapplication.cpp:2878
#42 in QCoreApplication::notifyInternal (this=0x8077970, receiver=0x80d1a80, event=0x898d020) at kernel/qcoreapplication.cpp:867
#43 in QCoreApplication::sendEvent (receiver=0x80d1a80, event=0x898d020) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:232
#44 in QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=0, data=0x8073318) at kernel/qcoreapplication.cpp:1471
#45 in QCoreApplication::sendPostedEvents (receiver=0x0, event_type=0) at kernel/qcoreapplication.cpp:1329
#46 in QWindowSystemInterface::sendWindowSystemEvents (flags=...) at kernel/qwindowsysteminterface.cpp:560
#47 in QUnixEventDispatcherQPA::processEvents (this=0x8079958, flags=...) at eventdispatchers/qunixeventdispatcher.cpp:70
#48 in QEventLoop::processEvents (this=0xbfffef50, flags=...) at kernel/qeventloop.cpp:136
#49 in QEventLoop::exec (this=0xbfffef50, flags=...) at kernel/qeventloop.cpp:212
#50 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1120
#51 in QGuiApplication::exec () at kernel/qguiapplication.cpp:1220
#52 in QApplication::exec () at kernel/qapplication.cpp:2689
#53 in main(argc=2, argv=0xbffff294)
UPDATE2:
In response to those valuable comments of this question.
I also shared several detailed backtrace files in the following links: 1drv.ms/f/s!AlojS_vldQMhjHRlTfU9vwErNz-H .Please refer to Readme.txt
for for some explanation and the libc version I used.
By the way, when I tried to replace system() with vfork()/waitpid(), the freeze seems not appear any more. I did not know the reason.
Thanks you all in advance.
Without source code provided, it is hard to answer the question definitively. In my experience with multithreaded programs it is really easy to overlook some place, where a deadlock can occur. In your case it sounds like something, that is very unlikely to happen. However i would bet, that somewhere in your code you have a potential deadlock.
I would advise you to draw out the whole environment in a diagram and look at which threads use which shared ressources and when and where the mutexes come in.
But as i said in the beginning, without further information it's hard to say.
From the trace-back, it seems the malloc was called when Qt was trying to post an event.
If you are trying to send events across threads, Qt could Queue the events for you. But these events could fill up your memory if it is nor drained out. Then you could get wired behavior from malloc, because there is no memory left.
Do you have a mean to monitor the memory usage of your program and see if this happens everytime the memory gets filled up?
Do you have a way to reduce the memory that the system has and see if this problem comes up more often?
If above is indeed the issue, then you might take a look at this thread for the solution.
If you are using signals and slots to communicate across threads you should understand the different connection patterns.
Auto Connection (default) If the signal is emitted in the thread
which the receiving object has affinity then the behavior is the same
as the Direct Connection. Otherwise, the behavior is the same as the
Queued Connection.
Direct Connection The slot is invoked
immediately, when the signal is emitted. The slot is executed in the
emitter's thread, which is not necessarily the receiver's thread.
Queued Connection The slot is invoked when control returns to the
event loop of the receiver's thread. The slot is executed in the
receiver's thread.
Blocking Queued Connection The slot is invoked as
for the Queued Connection, except the current thread blocks until the
slot returns. Note: Using this type to connect objects in the same
thread will cause deadlock.
More here: https://doc.qt.io/archives/qt-5.6/threads-qobject.html
The question does need some code context though. Is this behavior occurring when you are passing data to the UI? If yes are you using QWidgets, QML, ...? A lot of the Qt patterns rely on signals/slots when rendering data to the UI.

Erlang: blocking C NIF call behavior

I have observed a blocking behavior of C NIFs when they were being called concurrently by many Erlang processes. Can it be made non-blocking? Is there a mutex at work here which I'm not able to comprehend?
P.S. A basic "Hello world" NIF can be tested by making it sleep for a hundred microseconds in case of a particular PID calling it. It can be observed that the other PIDs calling the NIF wait for that sleep to execute before their execution.
Non blocking behavior would be beneficial in cases where concurrency might not pose an issue(e.g. array push, counter increment).
I am sharing the links to 4 gists which comprise of a spawner, conc_nif_caller and niftest module respectively. I have tried to tinker with the value of Val and I have indeed observed a non-blocking behavior. This is confirmed by assigning a large integer parameter to the spawn_multiple_nif_callers function.
Links
spawner.erl,conc_nif_caller.erl,niftest.erl and finally niftest.c.
The line below is printed by the Erlang REPL on my Mac.
Erlang/OTP 17 [erts-6.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
NIF's themselves don't have any mutex. You could implement one in C, and there is one when you load NIF's object, but this should be done only once with loading module.
One thing that's might be happening (and I would bet that's what is going on), is you C code messes up Erlang scheduler(s).
A native function that do lengthy work before returning will degrade responsiveness of the VM, and may cause miscellaneous strange behaviors. Such strange behaviors include, but are not limited to, extreme memory usage, and bad load balancing between schedulers. Strange behaviors that might occur due to lengthy work may also vary between OTP releases.
and description of what lengty work means and how you could solve it.
In very few words (with quite few simplifications):
For core one scheduler is created. Each has a list of processes which he can run. If ones scheduler list is empty, he will try to still work from another one. This can fail, if there is nothing (or not enough) to still.
Erlang schedulers spends some amount of work in one process, than moves to another, spend there some amount of work, and move to another. And so on, and so one. This is very similar to scheduling in system processes.
One thing that very important here is calculating amount of work. As default each function call has assigned some number of reductions. Addition could have two, calling function in your module will have one, sending a message also a one, some build-in could have more (like list_to_binary). If we collect 2 000 reductions we move to another process.
So what is the cost of your C function? It's only one reduction.
Code like
loop() ->
call_nif_function(),
loop().
could be taking all whole hour, but scheduler will be stuck in this one process, because he still haven't count to 2 000 reductions. Or to put it in other words, he could be stuck inside NIF without possibility to move forward (at least any time soon).
There are few ways around this but general rule is stat NIF's should not take long time. So if you have long running C code, maybe you should use drivers instead. They should be much easier to implement and manage, that tinkering with NIF's.
I think the responses about long-running NIFs are off the mark, since your question says you're running some simple "hello world" code and are sleeping for just 100 us. It's true that ideally a NIF call shouldn't take more than a millisecond, but your NIFs likely won't cause scheduler issues unless they run consistently for tens of milliseconds at a time or more.
I have a simple NIF called rev/1 that takes a string argument, reverses it, and returns the reversed string. I stuck a usleep call in the middle of it, then spawned 100 concurrent Erlang processes to invoke it. The two thread stacktraces shown below, based on Erlang/OTP 17.3.2, show two Erlang scheduler threads both inside the rev/1 NIF simultaneously, one at a breakpoint I set on the NIF C function itself, the other blocked on the usleep inside the NIF:
Thread 18 (process 26016):
#0 rev (env=0x1050d0a50, argc=1, argv=0x102ecc340) at nt2.c:9
#1 0x000000010020f13d in process_main () at beam/beam_emu.c:3525
#2 0x00000001000d5b2f in sched_thread_func (vesdp=0x102829040) at beam/erl_process.c:7719
#3 a0x0000000100301e94 in thr_wrapper (vtwd=0x7fff5fbff068) at pthread/ethread.c:106
#4 0x00007fff8a106899 in _pthread_body ()
#5 0x00007fff8a10672a in _pthread_start ()
#6 0x00007fff8a10afc9 in thread_start ()
Thread 17 (process 26016):
#0 0x00007fff8a0fda3a in __semwait_signal ()
#1 0x00007fff8d205dc0 in nanosleep ()
#2 0x00007fff8d205cb2 in usleep ()
#3 0x000000010062ee65 in rev (env=0x104fcba50, argc=1, argv=0x102ec8280) at nt2.c:21
#4 0x000000010020f13d in process_main () at beam/beam_emu.c:3525
#5 0x00000001000d5b2f in sched_thread_func (vesdp=0x10281ed80) at beam/erl_process.c:7719
#6 0x0000000100301e94 in thr_wrapper (vtwd=0x7fff5fbff068) at pthread/ethread.c:106
#7 0x00007fff8a106899 in _pthread_body ()
#8 0x00007fff8a10672a in _pthread_start ()
#9 0x00007fff8a10afc9 in thread_start ()
If there were any mutexes within the Erlang emulator preventing concurrent NIF access, the stacktraces would not show both threads inside the C NIF.
It would be nice if you were to post your code so those willing to help resolve this issue could see what you're doing and perhaps help you find any bottlenecks. It would also be helpful if you were to tell us what version(s) of Erlang/OTP you're using.
NIF calls block the scheduler to which the process that called them is bound. So, for your example, if those other processes are on the same scheduler, they cannot call into the NIF until the first process finishes.
You cannot make an NIF call non-blocking in this regard. You can, however, spawn your own threads and offload the brunt of your work to them.
Such threads can send messages to local Erlang processes (processes on the same machine), and as such you can still get the response you desire by waiting for your spawned thread to send back a message.
A bad example:
static ERL_NIF_TERM my_function(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
MyStruct* args = new MyStruct(); // I like C++; so sue me
args->caller = enif_self();
ErlNifTid thread_id;
// Please remember, you must at some point rejoin the thread,
// so keep track of the thread_id
enif_thread_create("my_function_thread", &thread_id, my_worker_function, (void*)args, NULL);
return enif_make_atom(env, "ok");
}
void* my_worker_function(void* args) {
sleep(100);
ErlNifEnv* msg_env = enif_alloc_env();
ERL_NIF_TERM msg = enif_make_atom(msg_env, "ok");
enif_send(NULL, args->caller, msg_env, msg);
delete args;
return NULL;
}
And in your erlang source:
test_nif() ->
my_nif:my_function(),
receive
ok -> ok
end.
Something to that effect, anyway.

Cuda hangs on cudaDeviceSynchronize randomly [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I have a piece of GPU code that has worked for a while. I recently made a couple minor algorithmic changes, but they didn't touch the CUDA part.
I'm running production runs on a set of three Xeon machines, each with a 780 Ti in it. Each run takes about three minutes to complete, but at this point there have been two cases (out of 5000) where the application has hung for hours (until killed). Both were on the same machine.
The second time, I attached GDB to the running process, and got a backtrace that looks like
#0 0x00007fff077ffa01 in clock_gettime ()
#1 0x0000003e1ec03e46 in clock_gettime () from /lib64/librt.so.1
#2 0x00002b5b5e302a1e in ?? () from /usr/lib64/libcuda.so
#3 0x00002b5b5dca2294 in ?? () from /usr/lib64/libcuda.so
#4 0x00002b5b5dbbaa4f in ?? () from /usr/lib64/libcuda.so
#5 0x00002b5b5dba8cda in ?? () from /usr/lib64/libcuda.so
#6 0x00002b5b5db94c4f in cuCtxSynchronize () from /usr/lib64/libcuda.so
#7 0x000000000041cd8d in cudart::cudaApiDeviceSynchronize() ()
#8 0x0000000000441269 in cudaDeviceSynchronize ()
#9 0x0000000000408124 in main (argc=11, argv=0x7fff076fa1d8) at src/fraps3d.cu:200
I manually did a frame 8; return; to forcibly make it finish, which caused it to end up stuck on the next cudaDeviceSynchronize() call. Doing it again got it stuck on the next synchronization call after that (every time with the same frames 0 through 8). Extra strangely, the failure happened in the middle of the main loop, on the ~5000th time through.
After killing it, the next jobs starts and runs properly, so it doesn't appear to be a systemic failure of the execution host.
Any ideas about what could cause a random failure like this?
I'm compiling and running with V6.0.1, running with driver version 331.62.

strange thread deadlock with SDL 1.2 on raspberry pi

I have been working with a simple bi-threaded application with two threads running simultaneously. Each thread plots a figure(a triangle/ a rectangle) to a predefined and mutually exclusive section of the screen. That is, both threads, never write in each other's screen space.
After running the program for a long time, say 5hours or so, the main thread keeps running , but the other thread freezes(it doesn't die though).
I get this in backtrace o/p, which shows a deadlock I guess.
Thread 2 (Thread 0xb542f440 (LWP 2142)):
#0 0xb6e83258 in __lll_lock_wait ()
from /lib/arm-linux-gnueabihf/libpthread.so.0
#1 0xb6e7de38 in pthread_mutex_lock ()
from /lib/arm-linux-gnueabihf/libpthread.so.0
#2 0xb6ef8de4 in SDL_mutexP ()
from /usr/lib/arm-linux-gnueabihf/libSDL-1.2.so.0
#3 0xb6ef4058 in ?? () from /usr/lib/arm-linux-gnueabihf/libSDL-1.2.so.0
#4 0xb6ef4058 in ?? () from /usr/lib/arm-linux-gnueabihf/libSDL-1.2.so.0
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
Is it really a libSDL1.2 issue? Do I have to write explicit user defined mutex for every SDL_Blit/or other operations with SDL, that I am doing? Or is it something else that I am missing? How would I solve this issue?
I am using:
libSDL1.2 available in Raspberry Pi
libPthreads
libSDL_ttf
EDIT: gdb trace of the thread 2 mutex:
(gdb) p *(pthread_mutex_t*) 0xb542ed38
$3 = {_data = {_lock = 39257160, __count = 1048617, __owner = 0,
__kind = 7078021, _nusers = 0, {_spins = 0, _list = {_next = 0x0}}},
__size = "H\004W\002)\000\020\000\000\000\000\000\205\000l\000\000\000\000\000\000\000\000", __align = 39257160}
Let me know if you need more information.
This approach will only work with software surfaces (w/o hardware acceleration). With hardware surfaces it, at best, would lock and wait - which have no performance benefits anyway; and in bad case (judging by quick look at SDL source) it could end badly, by the simple logic how SDL_LockSurface works.
I'm not even sure your external mutexes would help, since hardware accelerated graphics access should almost always be locked to one thread (OpenGL is good example - each thread have it's own separate drawing context).
In short, i see no reason why you should use two threads for drawing, but in any case it isn't guaranteed to be thread-safe.

Resources