blob: 4aee4445b6128d279202a2de3f24462fb68c6457 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Host.mm -------------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include <dlfcn.h>
11#include <libgen.h>
12#include <mach/mach.h>
13#include <mach-o/dyld.h>
14#include <signal.h>
15#include <stddef.h>
16#include <sys/sysctl.h>
17#include <unistd.h>
18
19#include <map>
20#include <string>
21
22#include <objc/objc-auto.h>
23
24#include <Foundation/Foundation.h>
25
26#include "CFCBundle.h"
27#include "CFCReleaser.h"
28#include "CFCString.h"
29
30#include "lldb/Host/Host.h"
31#include "lldb/Core/ArchSpec.h"
32#include "lldb/Core/ConstString.h"
33#include "lldb/Core/Error.h"
34#include "lldb/Core/FileSpec.h"
35#include "lldb/Core/Log.h"
36#include "lldb/Core/StreamString.h"
37#include "lldb/Host/Mutex.h"
38#include "lldb/Target/Process.h"
39#include "lldb/Target/Target.h"
40#include "lldb/Target/TargetList.h"
41#include "lldb/lldb-private-log.h"
42
43using namespace lldb;
44using namespace lldb_private;
45
46//------------------------------------------------------------------
47// Return the size in bytes of a page on the host system
48//------------------------------------------------------------------
49size_t
50Host::GetPageSize()
51{
52 return ::getpagesize();
53}
54
55
56//------------------------------------------------------------------
57// Returns true if the host system is Big Endian.
58//------------------------------------------------------------------
59ByteOrder
60Host::GetByteOrder()
61{
62 union EndianTest
63 {
64 uint32_t num;
65 uint8_t bytes[sizeof(uint32_t)];
66 } endian = { (uint16_t)0x11223344 };
67 switch (endian.bytes[0])
68 {
69 case 0x11: return eByteOrderLittle;
70 case 0x44: return eByteOrderBig;
71 case 0x33: return eByteOrderPDP;
72 }
73 return eByteOrderInvalid;
74}
75
76lldb::pid_t
77Host::GetCurrentProcessID()
78{
79 return ::getpid();
80}
81
82lldb::pid_t
83Host::GetCurrentThreadID()
84{
85 return ::mach_thread_self();
86}
87
88
89const ArchSpec &
90Host::GetArchitecture ()
91{
92 static ArchSpec g_host_arch;
93 if (!g_host_arch.IsValid())
94 {
95 uint32_t cputype, cpusubtype;
96 uint32_t is_64_bit_capable;
97 size_t len = sizeof(cputype);
98 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
99 {
100 len = sizeof(cpusubtype);
101 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
102 g_host_arch.SetArch(cputype, cpusubtype);
103
104 len = sizeof (is_64_bit_capable);
105 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
106 {
107 if (is_64_bit_capable)
108 {
109 if (cputype == CPU_TYPE_I386 && cpusubtype == CPU_SUBTYPE_486)
110 cpusubtype = CPU_SUBTYPE_I386_ALL;
111
112 cputype |= CPU_ARCH_ABI64;
113 }
114 }
115 }
116 }
117 return g_host_arch;
118}
119
120const ConstString &
121Host::GetVendorString()
122{
123 static ConstString g_vendor;
124 if (!g_vendor)
125 {
126 char ostype[64];
127 size_t len = sizeof(ostype);
128 if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
129 g_vendor.SetCString (ostype);
130 }
131 return g_vendor;
132}
133
134const ConstString &
135Host::GetOSString()
136{
137 static ConstString g_os_string("apple");
138 return g_os_string;
139}
140
141const ConstString &
142Host::GetTargetTriple()
143{
144 static ConstString g_host_triple;
145 if (!(g_host_triple))
146 {
147 StreamString triple;
148 triple.Printf("%s-%s-%s",
149 GetArchitecture ().AsCString(),
150 GetVendorString().AsCString("apple"),
151 GetOSString().AsCString("darwin"));
152
153 std::transform (triple.GetString().begin(),
154 triple.GetString().end(),
155 triple.GetString().begin(),
156 ::tolower);
157
158 g_host_triple.SetCString(triple.GetString().c_str());
159 }
160 return g_host_triple;
161}
162
163class MacOSXDarwinThread
164{
165public:
166 MacOSXDarwinThread(const char *thread_name) :
167 m_pool (nil)
168 {
169 // Register our thread with the collector if garbage collection is enabled.
170 if (objc_collectingEnabled())
171 {
172#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
173 // On Leopard and earlier there is no way objc_registerThreadWithCollector
174 // function, so we do it manually.
175 auto_zone_register_thread(auto_zone());
176#else
177 // On SnowLoepard and later we just call the thread registration function.
178 objc_registerThreadWithCollector();
179#endif
180 }
181 else
182 {
183 m_pool = [[NSAutoreleasePool alloc] init];
184 }
185
186
187 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
188 }
189
190 ~MacOSXDarwinThread()
191 {
192 if (m_pool)
193 [m_pool release];
194 }
195
196 static void PThreadDestructor (void *v)
197 {
198 delete (MacOSXDarwinThread*)v;
199 }
200
201protected:
202 NSAutoreleasePool * m_pool;
203private:
204 DISALLOW_COPY_AND_ASSIGN (MacOSXDarwinThread);
205};
206
207static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
208static pthread_key_t g_thread_create_key = 0;
209
210static void
211InitThreadCreated()
212{
213 ::pthread_key_create (&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor);
214}
215
Greg Claytonc0418152010-07-07 17:07:17 +0000216struct HostThreadCreateInfo
Chris Lattner24943d22010-06-08 16:52:24 +0000217{
218 std::string thread_name;
219 thread_func_t thread_fptr;
220 thread_arg_t thread_arg;
221
222 HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) :
223 thread_name (name ? name : ""),
224 thread_fptr (fptr),
225 thread_arg (arg)
226 {
227 }
228};
229
230static thread_result_t
231ThreadCreateTrampoline (thread_arg_t arg)
232{
233 HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg;
234 Host::ThreadCreated (info->thread_name.c_str());
235 thread_func_t thread_fptr = info->thread_fptr;
236 thread_arg_t thread_arg = info->thread_arg;
237
238 Log * log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
239 if (log)
240 log->Printf("thread created");
241
242 delete info;
243 return thread_fptr (thread_arg);
244}
245
246lldb::thread_t
247Host::ThreadCreate
248(
249 const char *thread_name,
250 thread_func_t thread_fptr,
251 thread_arg_t thread_arg,
252 Error *error
253)
254{
255 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
256
257 // Host::ThreadCreateTrampoline will delete this pointer for us.
258 HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg);
259
260 int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr);
261 if (err == 0)
262 {
263 if (error)
264 error->Clear();
265 return thread;
266 }
267
268 if (error)
269 error->SetError (err, eErrorTypePOSIX);
270
271 return LLDB_INVALID_HOST_THREAD;
272}
273
274bool
275Host::ThreadCancel (lldb::thread_t thread, Error *error)
276{
277
278 int err = ::pthread_cancel (thread);
279 if (error)
280 error->SetError(err, eErrorTypePOSIX);
281 return err == 0;
282}
283
284bool
285Host::ThreadDetach (lldb::thread_t thread, Error *error)
286{
287 int err = ::pthread_detach (thread);
288 if (error)
289 error->SetError(err, eErrorTypePOSIX);
290 return err == 0;
291}
292
293bool
294Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error)
295{
296 int err = ::pthread_join (thread, thread_result_ptr);
297 if (error)
298 error->SetError(err, eErrorTypePOSIX);
299 return err == 0;
300}
301
302void
303Host::ThreadCreated (const char *thread_name)
304{
305 ::pthread_once (&g_thread_create_once, InitThreadCreated);
306 if (g_thread_create_key)
307 {
308 ::pthread_setspecific (g_thread_create_key, new MacOSXDarwinThread(thread_name));
309 }
310}
311
312//------------------------------------------------------------------
313// Control access to a static file thread name map using a single
314// static function to avoid a static constructor.
315//------------------------------------------------------------------
316static const char *
317ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name)
318{
319
320 uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid;
321
322 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
323 Mutex::Locker locker(&g_mutex);
324
325 typedef std::map<uint64_t, std::string> thread_name_map;
326 static thread_name_map g_thread_names;
327
328 if (get)
329 {
330 // See if the thread name exists in our thread name pool
331 thread_name_map::iterator pos = g_thread_names.find(pid_tid);
332 if (pos != g_thread_names.end())
333 return pos->second.c_str();
334 }
335 else
336 {
337 // Set the thread name
338 g_thread_names[pid_tid] = name;
339 }
340 return NULL;
341}
342
343
344
345const char *
346Host::GetSignalAsCString (int signo)
347{
348 switch (signo)
349 {
350 case SIGHUP: return "SIGHUP"; // 1 hangup
351 case SIGINT: return "SIGINT"; // 2 interrupt
352 case SIGQUIT: return "SIGQUIT"; // 3 quit
353 case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught)
354 case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught)
355 case SIGABRT: return "SIGABRT"; // 6 abort()
356#if defined(_POSIX_C_SOURCE)
357 case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
358#else // !_POSIX_C_SOURCE
359 case SIGEMT: return "SIGEMT"; // 7 EMT instruction
360#endif // !_POSIX_C_SOURCE
361 case SIGFPE: return "SIGFPE"; // 8 floating point exception
362 case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored)
363 case SIGBUS: return "SIGBUS"; // 10 bus error
364 case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation
365 case SIGSYS: return "SIGSYS"; // 12 bad argument to system call
366 case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it
367 case SIGALRM: return "SIGALRM"; // 14 alarm clock
368 case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill
369 case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel
370 case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty
371 case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty
372 case SIGCONT: return "SIGCONT"; // 19 continue a stopped process
373 case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit
374 case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read
375 case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local&LTOSTOP)
376#if !defined(_POSIX_C_SOURCE)
377 case SIGIO: return "SIGIO"; // 23 input/output possible signal
378#endif
379 case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit
380 case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit
381 case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm
382 case SIGPROF: return "SIGPROF"; // 27 profiling time alarm
383#if !defined(_POSIX_C_SOURCE)
384 case SIGWINCH: return "SIGWINCH"; // 28 window size changes
385 case SIGINFO: return "SIGINFO"; // 29 information request
386#endif
387 case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1
388 case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2
389 default:
390 break;
391 }
392 return NULL;
393}
394
395const char *
396Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
397{
398 const char *name = ThreadNameAccessor (true, pid, tid, NULL);
399 if (name == NULL)
400 {
401 // We currently can only get the name of a thread in the current process.
402#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
403 if (pid == Host::GetCurrentProcessID())
404 {
405 char pthread_name[1024];
406 if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
407 {
408 if (pthread_name[0])
409 {
410 // Set the thread in our string pool
411 ThreadNameAccessor (false, pid, tid, pthread_name);
412 // Get our copy of the thread name string
413 name = ThreadNameAccessor (true, pid, tid, NULL);
414 }
415 }
416 }
417#endif
418 }
419 return name;
420}
421
422void
423Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
424{
425 lldb::pid_t curr_pid = Host::GetCurrentProcessID();
426 lldb::tid_t curr_tid = Host::GetCurrentThreadID();
427 if (pid == LLDB_INVALID_PROCESS_ID)
428 pid = curr_pid;
429
430 if (tid == LLDB_INVALID_THREAD_ID)
431 tid = curr_tid;
432
433#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
434 // Set the pthread name if possible
435 if (pid == curr_pid && tid == curr_tid)
436 {
437 ::pthread_setname_np (name) == 0;
438 }
439#endif
440 ThreadNameAccessor (false, pid, tid, name);
441}
442
443FileSpec
444Host::GetProgramFileSpec ()
445{
446 static FileSpec g_program_filepsec;
447 if (!g_program_filepsec)
448 {
449 std::string program_fullpath;
450 program_fullpath.resize (PATH_MAX);
451 // If DST is NULL, then return the number of bytes needed.
452 uint32_t len = program_fullpath.size();
453 int err = _NSGetExecutablePath ((char *)program_fullpath.data(), &len);
454 if (err < 0)
455 {
456 // The path didn't fit in the buffer provided, increase its size
457 // and try again
458 program_fullpath.resize(len);
459 len = program_fullpath.size();
460 err = _NSGetExecutablePath ((char *)program_fullpath.data(), &len);
461 }
462 if (err == 0)
463 g_program_filepsec.SetFile(program_fullpath.data());
464 }
465 return g_program_filepsec;
466}
467
468
469FileSpec
470Host::GetModuleFileSpecForHostAddress (const void *host_addr)
471{
472 FileSpec module_filespec;
473 Dl_info info;
474 if (::dladdr (host_addr, &info))
475 {
476 if (info.dli_fname)
477 module_filespec.SetFile(info.dli_fname);
478 }
479 return module_filespec;
480}
481
482
483bool
484Host::ResolveExecutableInBundle (FileSpec *file)
485{
486 if (file->GetFileType () == FileSpec::eFileTypeDirectory)
487 {
488 char path[PATH_MAX];
489 if (file->GetPath(path, sizeof(path)))
490 {
491 CFCBundle bundle (path);
492 CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
493 if (url.get())
494 {
495 if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
496 {
497 file->SetFile(path);
498 return true;
499 }
500 }
501 }
502 }
503 return false;
504}
505
Greg Claytonc0418152010-07-07 17:07:17 +0000506struct MonitorInfo
Chris Lattner24943d22010-06-08 16:52:24 +0000507{
508 int handle;
509 pthread_t thread;
510 Host::MonitorChildProcessCallback callback;
511 void *callback_baton;
512 bool monitor_signals;
513};
514
515typedef std::multimap<lldb::pid_t, MonitorInfo> MonitorInfoMap;
516static pthread_mutex_t g_monitor_map_mutex = PTHREAD_MUTEX_INITIALIZER;
517typedef lldb::SharedPtr<MonitorInfoMap>::Type MonitorInfoMapSP;
518
519static MonitorInfoMapSP&
520GetMonitorMap (bool can_create)
521{
522 static MonitorInfoMapSP g_monitor_map_sp;
523 if (can_create && g_monitor_map_sp.get() == NULL)
524 {
525 g_monitor_map_sp.reset (new MonitorInfoMap);
526 }
527 return g_monitor_map_sp;
528}
529
530static Predicate<bool>&
531GetChildProcessPredicate ()
532{
533 static Predicate<bool> g_has_child_processes;
534 return g_has_child_processes;
535}
536
537static void *
538MonitorChildProcessThreadFunction (void *arg);
539
540static pthread_t g_monitor_thread;
541
542uint32_t
543Host::StartMonitoringChildProcess
544(
545 MonitorChildProcessCallback callback,
546 void *callback_baton,
547 lldb::pid_t pid,
548 bool monitor_signals
549)
550{
551 static uint32_t g_handle = 0;
552 if (callback)
553 {
554 Mutex::Locker locker(&g_monitor_map_mutex);
555 if (!g_monitor_thread)
556 {
Greg Claytonf2a4d2e2010-07-06 20:27:00 +0000557 lldb::pid_t wait_pid = -1;
Chris Lattner24943d22010-06-08 16:52:24 +0000558 g_monitor_thread = ThreadCreate ("<lldb.host.wait4>",
559 MonitorChildProcessThreadFunction,
560 &wait_pid,
561 NULL);
562 if (g_monitor_thread)
563 {
564 //Host::ThreadDetach (g_monitor_thread, NULL);
565 }
566 }
567
568 if (g_monitor_thread)
569 {
570 MonitorInfo info = { ++g_handle, 0, callback, callback_baton, monitor_signals };
571 MonitorInfoMapSP monitor_map_sp (GetMonitorMap (true));
572 if (monitor_map_sp)
573 {
574 monitor_map_sp->insert(std::make_pair(pid, info));
575 GetChildProcessPredicate ().SetValue (true, eBroadcastOnChange);
576 return info.handle;
577 }
578 }
579 }
580 return 0;
581}
582
583bool
584Host::StopMonitoringChildProcess (uint32_t handle)
585{
586 Mutex::Locker locker(&g_monitor_map_mutex);
587 MonitorInfoMapSP monitor_map_sp (GetMonitorMap (false));
588 if (monitor_map_sp)
589 {
590 MonitorInfoMap::iterator pos, end = monitor_map_sp->end();
591 for (pos = monitor_map_sp->end(); pos != end; ++pos)
592 {
593 if (pos->second.handle == handle)
594 {
595 monitor_map_sp->erase(pos);
596 return true;
597 }
598 }
599 }
600 return false;
601}
602
603
604//------------------------------------------------------------------
605// Scoped class that will disable thread canceling when it is
606// constructed, and exception safely restore the previous value it
607// when it goes out of scope.
608//------------------------------------------------------------------
609class ScopedPThreadCancelDisabler
610{
611public:
612
613 ScopedPThreadCancelDisabler()
614 {
615 // Disable the ability for this thread to be cancelled
616 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state);
617 if (err != 0)
618 m_old_state = -1;
619
620 }
621
622 ~ScopedPThreadCancelDisabler()
623 {
624 // Restore the ability for this thread to be cancelled to what it
625 // previously was.
626 if (m_old_state != -1)
627 ::pthread_setcancelstate (m_old_state, 0);
628 }
629private:
630 int m_old_state; // Save the old cancelability state.
631};
632
633
634
635static void *
636MonitorChildProcessThreadFunction (void *arg)
637{
638 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
639 const char *function = __FUNCTION__;
640 if (log)
641 log->Printf ("%s (arg = %p) thread starting...", function, arg);
642
Greg Claytonf2a4d2e2010-07-06 20:27:00 +0000643 const lldb::pid_t wait_pid = -1;//*((pid_t*)arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000644 int status = -1;
645 const int options = 0;
646 struct rusage *rusage = NULL;
647 while (1)
648 {
649 if (log)
650 log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, wait_pid, options, rusage);
651
652 // Wait for all child processes
653 ::pthread_testcancel ();
654 lldb::pid_t pid = ::wait4 (wait_pid, &status, options, rusage);
655 ::pthread_testcancel ();
656
657 if (pid < 0)
658 {
659 // No child processes to watch wait for the mutex to be cleared
660
661 // Scope for "locker"
662 {
663 ScopedPThreadCancelDisabler pthread_cancel_disabler;
664
665 // First clear out all monitor entries since we have no processes
666 // to watch.
667 Mutex::Locker locker(&g_monitor_map_mutex);
668 // Since we don't have any child processes, we can safely clear
669 // anyone with a valid pid.
670 MonitorInfoMapSP monitor_map_sp(GetMonitorMap (false));
671 if (monitor_map_sp)
672 {
673 MonitorInfoMap::iterator pos = monitor_map_sp->begin();
674 while (pos != monitor_map_sp->end())
675 {
676 // pid value of 0 and -1 are special (see man page on wait4...)
677 if (pos->first > 0)
678 {
679 MonitorInfoMap::iterator next_pos = pos; ++next_pos;
680 monitor_map_sp->erase (pos, next_pos);
681 pos = next_pos;
682 }
683 else
684 ++pos;
685 }
686 }
687 }
688
689 if (log)
690 log->Printf("%s no child processes, wait for some...", function);
691 GetChildProcessPredicate ().SetValue (false, eBroadcastNever);
692 ::pthread_testcancel();
693 GetChildProcessPredicate ().WaitForValueEqualTo (true);
694 if (log)
695 log->Printf("%s resuming monitoring of child processes.", function);
696
697 }
698 else
699 {
700 ScopedPThreadCancelDisabler pthread_cancel_disabler;
701 bool exited = false;
702 int signal = 0;
703 int exit_status = 0;
704 const char *status_cstr = NULL;
705 if (WIFSTOPPED(status))
706 {
707 signal = WSTOPSIG(status);
708 status_cstr = "STOPPED";
709 }
710 else if (WIFEXITED(status))
711 {
712 exit_status = WEXITSTATUS(status);
713 status_cstr = "EXITED";
714 exited = true;
715 }
716 else if (WIFSIGNALED(status))
717 {
718 signal = WTERMSIG(status);
719 status_cstr = "SIGNALED";
720 exited = true;
721 exit_status = -1;
722 }
723 else
724 {
725 status_cstr = "(???)";
726 }
727
728 if (log)
729 log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
730 function,
731 wait_pid,
732 options,
733 rusage,
734 pid,
735 status,
736 status_cstr,
737 signal,
738 exit_status);
739
740 // Scope for mutex locker
741 {
742 // Notify anyone listening to this process
743 Mutex::Locker locker(&g_monitor_map_mutex);
744 MonitorInfoMapSP monitor_map_sp(GetMonitorMap (false));
745 if (monitor_map_sp)
746 {
747 std::pair<MonitorInfoMap::iterator, MonitorInfoMap::iterator> range;
748 range = monitor_map_sp->equal_range(pid);
749 MonitorInfoMap::iterator pos;
750 for (pos = range.first; pos != range.second; ++pos)
751 {
752 if (exited || (signal != 0 && pos->second.monitor_signals))
753 {
754 bool callback_return = pos->second.callback (pos->second.callback_baton, pid, signal, exit_status);
755
756 if (exited || callback_return)
757 {
758 // Make this entry as needing to be removed by
759 // setting its handle to zero
760 pos->second.handle = 0;
761 }
762 }
763 }
764
765 // Remove any entries that requested to be removed or any
766 // entries for child processes that did exit. We know this
767 // because we changed the handles to an invalid value.
768 pos = monitor_map_sp->begin();
769 while (pos != monitor_map_sp->end())
770 {
771 if (pos->second.handle == 0)
772 {
773 MonitorInfoMap::iterator next_pos = pos; ++next_pos;
774 monitor_map_sp->erase (pos, next_pos);
775 pos = next_pos;
776 }
777 else
778 ++pos;
779 }
780 }
781 }
782 }
783 }
784
785 if (log)
786 log->Printf ("ProcessMacOSX::%s (arg = %p) thread exiting...", __FUNCTION__, arg);
787
788 g_monitor_thread = NULL;
789 return NULL;
790}
791
792void
793Host::WillTerminate ()
794{
795 if (g_monitor_thread != NULL)
796 {
797 ThreadCancel (g_monitor_thread, NULL);
798 GetChildProcessPredicate ().SetValue (true, eBroadcastAlways);
799 ThreadJoin(g_monitor_thread, NULL, NULL);
800 g_monitor_thread = NULL;
801 }
802}
803