Mach allows you to suspend and resume other threads within a program, so
debugserver has to be careful not to interfere with this when it goes to supend and
resume threads while stepping over breakpoints and calling functions. Even
trickier, if you call a function on a suspended thread, it has to resume the
thread to get the expression to run, and then suspend it properly when done.
This all works already, but there wasn't a test for it. Adding that here.
This same test could be written for a unix that supports pthread_{suspend,resume}_np, but
macOS doesn't support these calls, only the mach version. It doesn't look like
a lot of Linux'es support this (AIX does apparently...) And IIUC Windows allows
you to suspend and resume other threads, but the code for that would look pretty
different than this main.c. So for simplicity's sake I wrote this test for Darwin-only.
59 lines
1.4 KiB
C
59 lines
1.4 KiB
C
#include <pthread.h>
|
|
#include <mach/thread_act.h>
|
|
#include <unistd.h>
|
|
|
|
pthread_mutex_t suspend_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
pthread_mutex_t signal_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
pthread_cond_t signal_cond = PTHREAD_COND_INITIALIZER;
|
|
|
|
int g_running_count = 0;
|
|
|
|
int
|
|
function_to_call() {
|
|
return g_running_count;
|
|
}
|
|
|
|
void *
|
|
suspend_func (void *unused) {
|
|
pthread_setname_np("Look for me");
|
|
pthread_cond_signal(&signal_cond);
|
|
pthread_mutex_lock(&suspend_mutex);
|
|
|
|
return NULL; // We allowed the suspend thread to run
|
|
}
|
|
|
|
void *
|
|
running_func (void *input) {
|
|
while (g_running_count < 10) {
|
|
usleep (100);
|
|
g_running_count++; // Break here to show we can handle breakpoints
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
pthread_t suspend_thread; // Stop here to get things going
|
|
|
|
pthread_mutex_lock(&suspend_mutex);
|
|
pthread_mutex_lock(&signal_mutex);
|
|
pthread_create(&suspend_thread, NULL, suspend_func, NULL);
|
|
|
|
pthread_cond_wait(&signal_cond, &signal_mutex);
|
|
|
|
mach_port_t th_port = pthread_mach_thread_np(suspend_thread);
|
|
thread_suspend(th_port);
|
|
|
|
pthread_mutex_unlock(&suspend_mutex);
|
|
|
|
pthread_t running_thread;
|
|
pthread_create(&running_thread, NULL, running_func, NULL);
|
|
|
|
pthread_join(running_thread, NULL);
|
|
thread_resume(th_port); // Break here after thread_join
|
|
|
|
pthread_join(suspend_thread, NULL);
|
|
return 0; // Break here to make sure the thread exited normally
|
|
}
|