Welcome to mirror list, hosted at ThFree Co, Russian Federation.

loaded-images.c « metadata « mono - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9cb57828234c53f17597b1c4e54d640559d441df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "config.h"

#include "mono/metadata/loaded-images-internals.h"
#include "mono/metadata/image-internals.h"
#include "mono/metadata/metadata-internals.h"
#include "mono/utils/mono-logger-internals.h"

void
mono_loaded_images_init (MonoLoadedImages *li, MonoAssemblyLoadContext *owner)
{
	li->owner = owner;
	for (int hash_idx = 0; hash_idx < MONO_LOADED_IMAGES_HASH_COUNT; hash_idx++)
		li->loaded_images_hashes [hash_idx] = g_hash_table_new (g_str_hash, g_str_equal);
}

void
mono_loaded_images_cleanup (MonoLoadedImages *li, gboolean shutdown)
{
	if (shutdown) {
		GHashTableIter iter;
		MonoImage *image;

		// If an assembly image is still loaded at shutdown, this could indicate managed code is still running.
		// Reflection-only images being still loaded doesn't indicate anything as harmful, so we don't check for it.
		g_hash_table_iter_init (&iter, mono_loaded_images_get_hash (li, FALSE));
		while (g_hash_table_iter_next (&iter, NULL, (void**)&image))
			mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly image '%s' [%p] still loaded at shutdown.", image->name, image);
	}

	for (int hash_idx = 0; hash_idx < MONO_LOADED_IMAGES_HASH_COUNT; hash_idx++) {
		g_hash_table_destroy (li->loaded_images_hashes [hash_idx]);
		li->loaded_images_hashes [hash_idx] = NULL;
	}
}

void
mono_loaded_images_free (MonoLoadedImages *li)
{
	mono_loaded_images_cleanup (li, FALSE);
	g_free (li);
}

GHashTable *
mono_loaded_images_get_hash (MonoLoadedImages *li, gboolean refonly)
{
	g_assert (li != NULL);
	GHashTable **loaded_images_hashes = &li->loaded_images_hashes[0];
	int idx = refonly ? MONO_LOADED_IMAGES_HASH_PATH_REFONLY : MONO_LOADED_IMAGES_HASH_PATH;
	return loaded_images_hashes [idx];
}

GHashTable *
mono_loaded_images_get_by_name_hash (MonoLoadedImages *li, gboolean refonly)
{
	g_assert (li != NULL);
	GHashTable **loaded_images_hashes = &li->loaded_images_hashes[0];
	int idx = refonly ? MONO_LOADED_IMAGES_HASH_NAME_REFONLY : MONO_LOADED_IMAGES_HASH_NAME;
	return loaded_images_hashes [idx];
}

static MonoLoadedImages *
loaded_images_get_owner (MonoImage *image)
{
	/* image->alc could be NULL if we're closing an image that wasn't
	 * registered yet (for example if two threads raced to open it and one
	 * of them lost) */
	MonoAssemblyLoadContext *alc = mono_image_get_alc (image);
	return mono_alc_get_loaded_images (alc);
}

/**
 * Atomically decrements the image refcount and removes it from the loaded
 * images hashes if the refcount becomes zero.
 *
 * Returns TRUE if image unloading should proceed or FALSE otherwise.
 *
 * LOCKING: takes the images lock
 */
gboolean
mono_loaded_images_remove_image (MonoImage *image)
{
	char *name = NULL;
	gboolean proceed = FALSE;
	/*
	 * Atomically decrement the refcount and remove ourselves from the hash tables, so
	 * register_image () can't grab an image which is being closed.
	 */
	mono_images_lock ();

	if (mono_atomic_dec_i32 (&image->ref_count) > 0)
		goto done;

	MonoLoadedImages *li;
	li = loaded_images_get_owner (image);
	if (!li) {
		/* we weren't registered; maybe lost to another image */
		proceed = TRUE;
		goto done;
	}
	GHashTable *loaded_images, *loaded_images_by_name;
	MonoImage *image2;

	loaded_images         = mono_loaded_images_get_hash (li, image->ref_only);
	loaded_images_by_name = mono_loaded_images_get_by_name_hash (li, image->ref_only);

	name = image->name;
	image2 = (MonoImage *)g_hash_table_lookup (loaded_images, name);
	if (image == image2) {
		/* This is not true if we are called from mono_image_open () */
		g_hash_table_remove (loaded_images, name);
	}
	if (image->assembly_name && (g_hash_table_lookup (loaded_images_by_name, image->assembly_name) == image))
		g_hash_table_remove (loaded_images_by_name, (char *) image->assembly_name);

	proceed = TRUE;
done:
	mono_images_unlock ();

	return proceed;
	
}

MonoLoadedImages*
mono_image_get_loaded_images_for_modules (MonoImage *image)
{
	return mono_get_global_loaded_images ();
}