Пример #1
0
Файл: gc.c Проект: sblom/mono
void
ves_icall_System_GC_WaitForPendingFinalizers (void)
{
#ifndef HAVE_NULL_GC
	if (!mono_gc_pending_finalizers ())
		return;

	if (mono_thread_internal_current () == gc_thread)
		/* Avoid deadlocks */
		return;

	/*
	If the finalizer thread is not live, lets pretend no finalizers are pending since the current thread might
	be the one responsible for starting it up.
	*/
	if (gc_thread == NULL)
		return;

	ResetEvent (pending_done_event);
	mono_gc_finalize_notify ();
	/* g_print ("Waiting for pending finalizers....\n"); */
	WaitForSingleObjectEx (pending_done_event, INFINITE, TRUE);
	/* g_print ("Done pending....\n"); */
#endif
}
MONO_SIG_HANDLER_FUNC (static, sigint_handler)
{
	int save_errno;

	if (in_sigint)
		return;

	in_sigint = TRUE;
	save_errno = errno;
	need_cancel = TRUE;
	mono_gc_finalize_notify ();
	errno = save_errno;
	in_sigint = FALSE;
}
Пример #3
0
static void
sigint_handler (int signo)
{
	int save_errno;
	MONO_ARCH_SAVE_REGS;

	if (in_sigint)
		return;

	in_sigint = TRUE;
	save_errno = errno;
	need_cancel = TRUE;
	mono_gc_finalize_notify ();
	errno = save_errno;
	in_sigint = FALSE;
}
Пример #4
0
void
ves_icall_System_GC_WaitForPendingFinalizers (void)
{
#ifndef HAVE_NULL_GC
	if (!mono_gc_pending_finalizers ())
		return;

	if (mono_thread_internal_current () == gc_thread)
		/* Avoid deadlocks */
		return;

	ResetEvent (pending_done_event);
	mono_gc_finalize_notify ();
	/* g_print ("Waiting for pending finalizers....\n"); */
	WaitForSingleObjectEx (pending_done_event, INFINITE, TRUE);
	/* g_print ("Done pending....\n"); */
#endif
}
Пример #5
0
/**
 * mono_attach_start:
 *
 * Start the attach mechanism if needed.  This is called from a signal handler so it must be signal safe.
 *
 * Returns: whenever it was started.
 */
gboolean
mono_attach_start (void)
{
	char path [256];
	int fd;

	if (started)
		return FALSE;

	/* Check for the existence of the trigger file */

	/* 
	 * We don't do anything with this file, and the only thing an attacker can do
	 * by creating it is to enable the attach mechanism if the process receives a 
	 * SIGQUIT signal, which can only be sent by the owner/root.
	 */
	snprintf (path, sizeof (path), "/tmp/.mono_attach_pid%"PRIdMAX"", (intmax_t) getpid ());
	fd = open (path, O_RDONLY);
	if (fd == -1)
		return FALSE;
	close (fd);

	if (!config.enabled)
		/* Act like we started */
		return TRUE;

	if (started)
		return FALSE;

	/*
	 * Our startup includes non signal-safe code, so ask the finalizer thread to 
	 * do the actual startup.
	 */
	needs_to_start = TRUE;
	mono_gc_finalize_notify ();

	return TRUE;
}
Пример #6
0
gboolean
mono_domain_finalize (MonoDomain *domain, guint32 timeout) 
{
	DomainFinalizationReq *req;
	guint32 res;
	HANDLE done_event;
	MonoInternalThread *thread = mono_thread_internal_current ();

	if (mono_thread_internal_current () == gc_thread)
		/* We are called from inside a finalizer, not much we can do here */
		return FALSE;

	/* 
	 * No need to create another thread 'cause the finalizer thread
	 * is still working and will take care of running the finalizers
	 */ 
	
#ifndef HAVE_NULL_GC
	if (gc_disabled)
		return TRUE;

	mono_gc_collect (mono_gc_max_generation ());

	done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
	if (done_event == NULL) {
		return FALSE;
	}

	req = g_new0 (DomainFinalizationReq, 1);
	req->domain = domain;
	req->done_event = done_event;

	if (domain == mono_get_root_domain ())
		finalizing_root_domain = TRUE;
	
	mono_finalizer_lock ();

	domains_to_finalize = g_slist_append (domains_to_finalize, req);

	mono_finalizer_unlock ();

	/* Tell the finalizer thread to finalize this appdomain */
	mono_gc_finalize_notify ();

	if (timeout == -1)
		timeout = INFINITE;

	while (TRUE) {
		res = WaitForSingleObjectEx (done_event, timeout, TRUE);
		/* printf ("WAIT RES: %d.\n", res); */

		if (res == WAIT_IO_COMPLETION) {
			if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0)
				return FALSE;
		} else if (res == WAIT_TIMEOUT) {
			/* We leak the handle here */
			return FALSE;
		} else {
			break;
		}
	}

	CloseHandle (done_event);

	if (domain == mono_get_root_domain ()) {
		mono_thread_pool_cleanup ();
		mono_gc_finalize_threadpool_threads ();
	}

	return TRUE;
#else
	/* We don't support domain finalization without a GC */
	return FALSE;
#endif
}
Пример #7
0
gboolean
mono_domain_finalize (MonoDomain *domain, guint32 timeout) 
{
	DomainFinalizationReq *req;
	MonoInternalThread *thread = mono_thread_internal_current ();
	gint res;
	gboolean ret;
	gint64 start;

#if defined(__native_client__)
	return FALSE;
#endif

	if (mono_thread_internal_current () == gc_thread)
		/* We are called from inside a finalizer, not much we can do here */
		return FALSE;

	/* 
	 * No need to create another thread 'cause the finalizer thread
	 * is still working and will take care of running the finalizers
	 */ 
	
	if (gc_disabled)
		return TRUE;

	/* We don't support domain finalization without a GC */
	if (mono_gc_is_null ())
		return FALSE;

	mono_gc_collect (mono_gc_max_generation ());

	req = g_new0 (DomainFinalizationReq, 1);
	req->ref = 2;
	req->domain = domain;
	mono_coop_sem_init (&req->done, 0);

	if (domain == mono_get_root_domain ())
		finalizing_root_domain = TRUE;
	
	mono_finalizer_lock ();

	domains_to_finalize = g_slist_append (domains_to_finalize, req);

	mono_finalizer_unlock ();

	/* Tell the finalizer thread to finalize this appdomain */
	mono_gc_finalize_notify ();

	if (timeout == -1)
		timeout = INFINITE;
	if (timeout != INFINITE)
		start = mono_msec_ticks ();

	ret = TRUE;

	for (;;) {
		if (timeout == INFINITE) {
			res = mono_coop_sem_wait (&req->done, MONO_SEM_FLAGS_ALERTABLE);
		} else {
			gint64 elapsed = mono_msec_ticks () - start;
			if (elapsed >= timeout) {
				ret = FALSE;
				break;
			}

			res = mono_coop_sem_timedwait (&req->done, timeout - elapsed, MONO_SEM_FLAGS_ALERTABLE);
		}

		if (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
			break;
		} else if (res == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
			if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) {
				ret = FALSE;
				break;
			}
		} else if (res == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
			ret = FALSE;
			break;
		} else {
			g_error ("%s: unknown result %d", __func__, res);
		}
	}

	if (!ret) {
		/* Try removing the req from domains_to_finalize:
		 *  - if it's not found: the domain is being finalized,
		 *     so we the ref count is already decremented
		 *  - if it's found: the domain is not yet being finalized,
		 *     so we can safely decrement the ref */

		gboolean found;

		mono_finalizer_lock ();

		found = g_slist_index (domains_to_finalize, req) != -1;
		if (found)
			domains_to_finalize = g_slist_remove (domains_to_finalize, req);

		mono_finalizer_unlock ();

		if (found) {
			/* We have to decrement it wherever we
			 * remove it from domains_to_finalize */
			if (InterlockedDecrement (&req->ref) != 1)
				g_error ("%s: req->ref should be 1, as we are the first one to decrement it", __func__);
		}

		goto done;
	}

	if (domain == mono_get_root_domain ()) {
		mono_threadpool_ms_cleanup ();
		mono_gc_finalize_threadpool_threads ();
	}

done:
	if (InterlockedDecrement (&req->ref) == 0) {
		mono_coop_sem_destroy (&req->done);
		g_free (req);
	}

	return ret;
}