Strange RunTime Error

Hey all,

I’m getting a strange runtime error with my app on one of my Macs, but not the other. It all starts when I am launching a couple of threads.

Here’s the error message:

Location: Common/ClassLib/
RuntimeThreadPlatformPOSIX.cpp:66
Condition: err == 00
Message: pthread_create: 35

Here is part of the crash log after the app crashes:

Crashed Thread:        4092

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Application Specific Information:
Assertion failed: (err == 0, "pthread_create: 35"), function SpawnThread, file Common/ClassLib/RuntimeThreadPlatformPOSIX.cpp, line 66.
 

Thread 0:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fff5cafaa16 __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff5ccc3589 _pthread_cond_wait + 732
2   com.xojo.XojoFramework        	0x000000010cfe5fd8 xojo::ConditionVariable::Wait(xojo::UniqueLock&) + 12
3   com.xojo.XojoFramework        	0x000000010d12d395 0x10ceb2000 + 2601877
4   com.xojo.XojoFramework        	0x000000010d12b254 0x10ceb2000 + 2593364
5   com.justaddsoftware.mediaswitcher	0x000000010afa37ab Thread.Run%%o<Thread> + 11
6   com.justaddsoftware.mediaswitcher	0x000000010be2a16e AutoObject.AutomationAction%%o<AutoObject> + 78
7   com.justaddsoftware.mediaswitcher	0x000000010b6c6db4 AutomationTimer.Event_Action%%o<AutomationTimer> + 932

It happens one on machine but not the other.

I am running 2019r3.1

What could this be?

how many threads?
What stack size?

Xojo complains that pthread_create doesn’t return zero.

I made a case: 62534 - SpawnThread method should raise error if pthread_create doesn’t return zero.

Feel free to add a sample project.

Let me quote the pthread documentation:

PTHREAD_CREATE(3) BSD Library Functions Manual PTHREAD_CREATE(3)

NAME
pthread_create – create a new thread

SYNOPSIS
#include <pthread.h>

 int
 pthread_create(pthread_t *thread, const pthread_attr_t *attr,
     void *(*start_routine)(void *), void *arg);

DESCRIPTION
The pthread_create() function is used to create a new thread, with
attributes specified by attr, within a process. If attr is NULL, the
default attributes are used. If the attributes specified by attr are
modified later, the thread’s attributes are not affected. Upon success-
ful completion pthread_create() will store the ID of the created thread
in the location specified by thread.

 The thread is created executing start_routine with arg as its sole argu-
 ment.  If the start_routine returns, the effect is as if there was an
 implicit call to pthread_exit() using the return value of start_routine
 as the exit status.  Note that the thread in which main() was originally
 invoked differs from this.  When it returns from main(), the effect is as
 if there was an implicit call to exit() using the return value of main()
 as the exit status.

 Upon thread exit the storage for the thread must be reclaimed by another
 thread via a call to pthread_join().  Alternatively, pthread_detach() may
 be called on the thread to indicate that the system may automatically
 reclaim the thread storage upon exit.  The pthread_attr_setdetachstate()
 function may be used on the attr argument passed to pthread_create() in
 order to achieve the same effect as a call to pthread_detach() on the
 newly created thread.

 The signal state of the new thread is initialized as:

       o   The signal mask is inherited from the creating thread.

       o   The set of signals pending for the new thread is empty.

RETURN VALUES
If successful, the pthread_create() function will return zero. Otherwise
an error number will be returned to indicate the error.

ERRORS
The pthread_create() function will fail if:

 [EAGAIN]           The system lacked the necessary resources to create
                    another thread, or the system-imposed limit on the
                    total number of threads in a process
                    [PTHREAD_THREADS_MAX] would be exceeded.

 [EPERM]            The caller does not have appropriate permission to set
                    the required scheduling parameters or scheduling pol-
                    icy.

 [EINVAL]           The value specified by attr is invalid.

SEE ALSO
fork(2), pthread_attr(3), pthread_cancel(3), pthread_cleanup_pop(3),
pthread_cleanup_push(3), pthread_exit(3), pthread_join(3)

STANDARDS
The pthread_create() function conforms to ISO/IEC 9945-1:1996
(``POSIX.1’').

BSD March 15, 2014 BSD

So you see the three ways it fails: out of resources, wrong parameter or permissions.

I’m trying to have maybe 3 threads at most and they should all be over fairly quickly. I’m automating some actions in the background of my app. A timer launches the first thread and then from that thread, two new ones are created. This all should be complete quite quickly.

On my MacBookPro, this works flawlessly. No issues. On an older MacMini (i5 CPU), I get the crash. But I have another MacMini also with an i5 and I’ve not seen the issue.

This has to be API2.0 related as I’ve spawned 10 to 15 threads in the past with no problem at all using Aaron Ballman’s thread pool manager.

No idea on the stack size. Again, there’s not a ton of processing going on. There’s just some things where I need to add delays and that’s really convenient to do in threads. I had been doing that by using timers but I was getting reports from customers of stuff not working right.

Have you tried to do everything in one thread?

That’s not so easy and I’ll tell you why.

I have what is effectively a remote control with a number of buttons on one of my windows. When the user presses one of these buttons, it launches a thread that sends commands to other devices over the network. Basically, turn a TV on, play a DVD player, etc.

I have a class that does all this.

But this can also be automated and completely done in code. So a user can schedule a button to be “pressed” at a specific time. So there’s another object that is scheduled that ends up “pressing” this button in code. And this AutomationObject as I am calling it can “press” multiple buttons and do multiple other functions in the app. So it’s not really possible to do them in the same thread.

Actually, Beatrix, I think I figured out how to make it all happen from the same thread. It wasn’t that hard once I went in and looked at my code.

I’m uploading to the problematic machine now…

Nope. That didn’t help either. Now I am spawning just one thread and it is still crashing…This is really strange.

When does the thread crash? At the start, somewhere in the middle?

OK. Something really, really weird is happening. Maybe I have something mucked up in my code. I tried running it but with the first object running from a timer instead of a thread. The application hung and when I looked at the crash report, it had a huge number of repeats of method calls.

So I decided to open activity viewer and look at the number of threads being created when I am using the thread to do the action. It shot up to 4096! No wonder it is crashing.

However, running the EXACT SAME build with the exact same settings, etc. on my MacBookPro, I generate no excessive threads.

I am stumped. I am going to perform a remote debugging session on that machine to see why it is basically going into an infinite loop.

Looks like this is an issue with my code that is basically spawning all these threads. I figured out the difference between the two machines in what was being done in what I was scheduling. There was one slight difference and I’ve been able to duplicate it.

Still Xojo should throw an exception as it is really similar to a stack overflow.

Yup. I figured it out. I had a bug in my code that could potentially cause the object I am running in the thread to basically re-execute itself in an infinite loop. It only happens in specific instances depending on what I was scheduling to happen. Pretty significant bug that is now fixed! Whew!

1 Like

The first crash report you posted also reveals this information:

Crashed Thread: 4092

The count of threads and the problem you had are rather obvious with that line.

Ah. That’s actually the number of threads. I thought that was an ID number. I saw the number go up viewing the application in Activity Monitor.

So I figured it out and it was an incorrect call I was making that would make the thread spawn another instance of itself.

Still Xojo should throw an exception in this case.

This could have been less than the number of threads, but, indeed, this is the index of the crashing thread, starting at 0, so there were at least this number of threads created (which looks really weird when you read it).

You made your first fork bomb, congratulations :wink:

I’m not sure Xojo observes the thread count, in fact.
StackOverflow exceptions come from the OS, which has a small memory to handle method calls (a pointer to the caller method (where to resume later, etc.) and such), and, if that memory is full and you try to call one more method, the StackOverflow exception is triggered (somewhat equivalent to an OutOfMemory exception).
I don’t know whether too many threads running can be handled as an exception by Xojo… :thinking:

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.