[metadata] Fix leaks when handling a few attributes (#16675)
[mono-project.git] / mono / metadata / fdhandle.c
blob39e531b514c5bad8c330b8f7ab9b112325aaaeb4
2 #include "fdhandle.h"
3 #include "utils/mono-lazy-init.h"
4 #include "utils/mono-coop-mutex.h"
6 static GHashTable *fds;
7 static MonoCoopMutex fds_mutex;
8 static MonoFDHandleCallback fds_callback[MONO_FDTYPE_COUNT];
9 static mono_lazy_init_t fds_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
11 static const gchar *types_str[] = {
12 "File",
13 "Console",
14 "Pipe",
15 "Socket",
16 NULL
19 static void
20 fds_remove (gpointer data)
22 MonoFDHandle* fdhandle;
24 fdhandle = (MonoFDHandle*) data;
25 g_assert (fdhandle);
27 g_assert (fds_callback [fdhandle->type].close);
28 fds_callback [fdhandle->type].close (fdhandle);
30 mono_refcount_dec (fdhandle);
33 static void
34 initialize (void)
36 fds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, fds_remove);
37 mono_coop_mutex_init (&fds_mutex);
40 void
41 mono_fdhandle_register (MonoFDType type, MonoFDHandleCallback *callback)
43 mono_lazy_initialize (&fds_init, initialize);
44 memcpy (&fds_callback [type], callback, sizeof (MonoFDHandleCallback));
47 static void
48 fdhandle_destroy (gpointer data)
50 MonoFDHandle* fdhandle;
52 fdhandle = (MonoFDHandle*) data;
53 g_assert (fdhandle);
55 g_assert (fds_callback [fdhandle->type].destroy);
56 fds_callback [fdhandle->type].destroy (fdhandle);
59 void
60 mono_fdhandle_init (MonoFDHandle *fdhandle, MonoFDType type, gint fd)
62 mono_refcount_init (fdhandle, fdhandle_destroy);
63 fdhandle->type = type;
64 fdhandle->fd = fd;
67 void
68 mono_fdhandle_insert (MonoFDHandle *fdhandle)
70 mono_coop_mutex_lock (&fds_mutex);
72 if (g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fdhandle->fd), NULL, NULL))
73 g_error("%s: duplicate %s fd %d", __func__, types_str [fdhandle->type], fdhandle->fd);
75 g_hash_table_insert (fds, GINT_TO_POINTER(fdhandle->fd), fdhandle);
77 mono_coop_mutex_unlock (&fds_mutex);
80 gboolean
81 mono_fdhandle_try_insert (MonoFDHandle *fdhandle)
83 mono_coop_mutex_lock (&fds_mutex);
85 if (g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fdhandle->fd), NULL, NULL)) {
86 /* we raced between 2 invocations of mono_fdhandle_try_insert */
87 mono_coop_mutex_unlock (&fds_mutex);
89 return FALSE;
92 g_hash_table_insert (fds, GINT_TO_POINTER(fdhandle->fd), fdhandle);
94 mono_coop_mutex_unlock (&fds_mutex);
96 return TRUE;
99 gboolean
100 mono_fdhandle_lookup_and_ref (gint fd, MonoFDHandle **fdhandle)
102 mono_coop_mutex_lock (&fds_mutex);
104 if (!g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fd), NULL, (gpointer*) fdhandle)) {
105 mono_coop_mutex_unlock (&fds_mutex);
106 return FALSE;
109 mono_refcount_inc (*fdhandle);
111 mono_coop_mutex_unlock (&fds_mutex);
113 return TRUE;
116 void
117 mono_fdhandle_unref (MonoFDHandle *fdhandle)
119 mono_refcount_dec (fdhandle);
122 gboolean
123 mono_fdhandle_close (gint fd)
125 MonoFDHandle *fdhandle;
126 gboolean removed;
128 mono_coop_mutex_lock (&fds_mutex);
130 if (!g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fd), NULL, (gpointer*) &fdhandle)) {
131 mono_coop_mutex_unlock (&fds_mutex);
133 return FALSE;
136 removed = g_hash_table_remove (fds, GINT_TO_POINTER(fdhandle->fd));
137 g_assert (removed);
139 mono_coop_mutex_unlock (&fds_mutex);
141 return TRUE;