Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / mono-perfcounters.c
index fb205e80eaff2781966cdb448262ac85e9bac19f..1a3123a30aad58811bbf8d07c6d0581ac029474e 100644 (file)
@@ -1,5 +1,5 @@
-/*
- * mono-perfcounters.c
+/**
+ * \file
  *
  * Performance counters support.
  *
 #include <mach/message.h>
 #include <mach/mach_host.h>
 #include <mach/host_info.h>
+#include <sys/sysctl.h>
 #endif
-#if defined (__NetBSD__) || defined (__APPLE__)
+#if defined (__NetBSD__)
+#include <sys/param.h>
 #include <sys/sysctl.h>
+#include <sys/vmmeter.h>
 #endif
 #include "metadata/mono-perfcounters.h"
 #include "metadata/appdomain.h"
@@ -45,7 +48,7 @@
 #include "utils/mono-networkinterfaces.h"
 #include "utils/mono-error-internals.h"
 #include "utils/atomic.h"
-#include <mono/io-layer/io-layer.h>
+#include "utils/unlocked.h"
 
 /* map of CounterSample.cs */
 struct _MonoCounterSample {
@@ -425,7 +428,7 @@ mono_determine_physical_ram_size (void)
        int mib[2] = {
                CTL_HW,
 #ifdef __NetBSD__
-               HW_PHYSMEM
+               HW_PHYSMEM64
 #else
                HW_MEMSIZE
 #endif
@@ -474,29 +477,22 @@ mono_determine_physical_ram_available_size (void)
 #elif defined (__NetBSD__)
        struct vmtotal vm_total;
        guint64 page_size;
-       int mib [2];
+       int mib[2];
        size_t len;
 
+       mib[0] = CTL_VM;
+       mib[1] = VM_METER;
 
-       mib = {
-               CTL_VM,
-#if defined (VM_METER)
-               VM_METER
-#else
-               VM_TOTAL
-#endif
-       };
        len = sizeof (vm_total);
        sysctl (mib, 2, &vm_total, &len, NULL, 0);
 
-       mib = {
-               CTL_HW,
-               HW_PAGESIZE
-       };
+       mib[0] = CTL_HW;
+       mib[1] = HW_PAGESIZE;
+
        len = sizeof (page_size);
-       sysctl (mib, 2, &page_size, &len, NULL, 0
+       sysctl (mib, 2, &page_size, &len, NULL, 0);
 
-       return ((guint64) value.t_free * page_size) / 1024;
+       return ((guint64) vm_total.t_free * page_size) / 1024;
 #elif defined (__APPLE__)
        mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
        mach_port_t host = mach_host_self();
@@ -802,16 +798,14 @@ fill_sample (MonoCounterSample *sample)
 }
 
 static int
-id_from_string (MonoString *instance, gboolean is_process)
+id_from_string (const gchar *id_str, gboolean is_process)
 {
        int id = -1;
-       if (mono_string_length (instance)) {
-               char *id_str = mono_string_to_utf8 (instance);
+       if (strcmp("", id_str) != 0) {
                char *end;
                id = strtol (id_str, &end, 0);
                if (end == id_str && !is_process)
                        id = -1;
-               g_free (id_str);
        }
        return id;
 }
@@ -849,7 +843,7 @@ get_cpu_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *
 }
 
 static void*
-cpu_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom)
+cpu_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom)
 {
        int id = id_from_string (instance, FALSE) << 5;
        const CounterDesc *cdesc;
@@ -910,7 +904,7 @@ network_cleanup (ImplVtable *vtable)
 }
 
 static void*
-network_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom)
+network_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom)
 {
        const CounterDesc *cdesc;
        NetworkVtableArg *narg;
@@ -919,7 +913,7 @@ network_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBool
 
        *custom = FALSE;
        if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_NETWORK], counter))) {
-               instance_name = mono_string_to_utf8 (instance);
+               instance_name = g_strdup (instance);
                narg = g_new0 (NetworkVtableArg, 1);
                narg->id = cdesc->id;
                narg->name = instance_name;
@@ -971,7 +965,7 @@ get_process_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSamp
 }
 
 static void*
-process_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom)
+process_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom)
 {
        int id = id_from_string (instance, TRUE) << 5;
        const CounterDesc *cdesc;
@@ -1009,7 +1003,7 @@ mono_mem_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample
 }
 
 static void*
-mono_mem_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom)
+mono_mem_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom)
 {
        const CounterDesc *cdesc;
        *custom = FALSE;
@@ -1041,15 +1035,13 @@ predef_readonly_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter
 }
 
 static ImplVtable*
-predef_vtable (void *arg, MonoString *instance)
+predef_vtable (void *arg, const gchar *pids)
 {
        MonoSharedArea *area;
        PredefVtable *vtable;
-       char *pids = mono_string_to_utf8 (instance);
        int pid;
 
        pid = atoi (pids);
-       g_free (pids);
        area = load_sarea_for_pid (pid);
        if (!area)
                return NULL;
@@ -1082,52 +1074,52 @@ predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter
        case CATEGORY_EXC:
                switch (id) {
                case COUNTER_EXC_THROWN:
-                       sample->rawValue = mono_perfcounters->exceptions_thrown;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->exceptions_thrown);
                        return TRUE;
                }
                break;
        case CATEGORY_ASPNET:
                switch (id) {
                case COUNTER_ASPNET_REQ_Q:
-                       sample->rawValue = mono_perfcounters->aspnet_requests_queued;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->aspnet_requests_queued);
                        return TRUE;
                case COUNTER_ASPNET_REQ_TOTAL:
-                       sample->rawValue = mono_perfcounters->aspnet_requests;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->aspnet_requests);
                        return TRUE;
                }
                break;
        case CATEGORY_THREADPOOL:
                switch (id) {
                case COUNTER_THREADPOOL_WORKITEMS:
-                       sample->rawValue = mono_perfcounters->threadpool_workitems;
+                       sample->rawValue = InterlockedRead64 (&mono_perfcounters->threadpool_workitems);
                        return TRUE;
                case COUNTER_THREADPOOL_IOWORKITEMS:
-                       sample->rawValue = mono_perfcounters->threadpool_ioworkitems;
+                       sample->rawValue = InterlockedRead64 (&mono_perfcounters->threadpool_ioworkitems);
                        return TRUE;
                case COUNTER_THREADPOOL_THREADS:
-                       sample->rawValue = mono_perfcounters->threadpool_threads;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->threadpool_threads);
                        return TRUE;
                case COUNTER_THREADPOOL_IOTHREADS:
-                       sample->rawValue = mono_perfcounters->threadpool_iothreads;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->threadpool_iothreads);
                        return TRUE;
                }
                break;
        case CATEGORY_JIT:
                switch (id) {
                case COUNTER_JIT_BYTES:
-                       sample->rawValue = mono_perfcounters->jit_bytes;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_bytes);
                        return TRUE;
                case COUNTER_JIT_METHODS:
-                       sample->rawValue = mono_perfcounters->jit_methods;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_methods);
                        return TRUE;
                case COUNTER_JIT_TIME:
-                       sample->rawValue = mono_perfcounters->jit_time;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_time);
                        return TRUE;
                case COUNTER_JIT_BYTES_PSEC:
-                       sample->rawValue = mono_perfcounters->jit_bytes;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_bytes);
                        return TRUE;
                case COUNTER_JIT_FAILURES:
-                       sample->rawValue = mono_perfcounters->jit_failures;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_failures);
                        return TRUE;
                }
                break;
@@ -1138,7 +1130,7 @@ predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter
 static gint64
 predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
 {
-       guint32 *volatile ptr = NULL;
+       gint32 *volatile ptr = NULL;
        gint64 *volatile ptr64 = NULL;
        int cat_id = GPOINTER_TO_INT (vtable->arg);
        int id = cat_id >> 16;
@@ -1152,8 +1144,8 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
                break;
        case CATEGORY_THREADPOOL:
                switch (id) {
-               case COUNTER_THREADPOOL_WORKITEMS: ptr64 = (gint64 *) &mono_perfcounters->threadpool_workitems; break;
-               case COUNTER_THREADPOOL_IOWORKITEMS: ptr64 = (gint64 *) &mono_perfcounters->threadpool_ioworkitems; break;
+               case COUNTER_THREADPOOL_WORKITEMS: ptr64 = &mono_perfcounters->threadpool_workitems; break;
+               case COUNTER_THREADPOOL_IOWORKITEMS: ptr64 = &mono_perfcounters->threadpool_ioworkitems; break;
                case COUNTER_THREADPOOL_THREADS: ptr = &mono_perfcounters->threadpool_threads; break;
                case COUNTER_THREADPOOL_IOTHREADS: ptr = &mono_perfcounters->threadpool_iothreads; break;
                }
@@ -1162,29 +1154,23 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
        if (ptr) {
                if (do_incr) {
                        if (value == 1)
-                               return InterlockedIncrement ((gint32 *) ptr); /* FIXME: sign */
+                               return InterlockedIncrement (ptr);
                        if (value == -1)
-                               return InterlockedDecrement ((gint32 *) ptr); /* FIXME: sign */
+                               return InterlockedDecrement (ptr);
 
-                       *ptr += value;
-                       return *ptr;
+                       return InterlockedAdd(ptr, value);
                }
                /* this can be non-atomic */
                *ptr = value;
                return value;
        } else if (ptr64) {
                if (do_incr) {
-                       /* FIXME: we need to do this atomically */
-                       /* No InterlockedIncrement64() yet */
-                       /*
                        if (value == 1)
-                               return InterlockedIncrement64 (ptr);
+                               return UnlockedIncrement64 (ptr64); /* FIXME: use InterlockedIncrement64 () */
                        if (value == -1)
-                               return InterlockedDecrement64 (ptr);
-                       */
+                               return UnlockedDecrement64 (ptr64); /* FIXME: use InterlockedDecrement64 () */
 
-                       *ptr64 += value;
-                       return *ptr64;
+                       return UnlockedAdd64 (ptr64, value); /* FIXME: use InterlockedAdd64 () */
                }
                /* this can be non-atomic */
                *ptr64 = value;
@@ -1194,13 +1180,13 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
 }
 
 static void*
-predef_writable_get_impl (int cat, MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom)
+predef_writable_get_impl (int cat, MonoString* counter, const gchar *instance, int *type, MonoBoolean *custom)
 {
        const CounterDesc *cdesc;
        *custom = TRUE;
        if ((cdesc = get_counter_in_category (&predef_categories [cat], counter))) {
                *type = cdesc->type;
-               if (instance == NULL || mono_string_compare_ascii (instance, "") == 0)
+               if (instance == NULL || strcmp (instance, "") == 0)
                        return create_vtable (GINT_TO_POINTER ((cdesc->id << 16) | cat), predef_writable_counter, predef_writable_update);
                else
                        return predef_vtable (GINT_TO_POINTER ((cdesc->id << 16) | cat), instance);
@@ -1298,17 +1284,19 @@ custom_get_value_address (SharedCounter *scounter, SharedInstance* sinst)
 }
 
 static void*
-custom_get_impl (SharedCategory *cat, MonoString* counter, MonoString* instance, int *type)
+custom_get_impl (SharedCategory *cat, MonoString *counter, MonoString* instance, int *type, MonoError *error)
 {
        SharedCounter *scounter;
        SharedInstance* inst;
        char *name;
 
+       error_init (error);
        scounter = find_custom_counter (cat, counter);
        if (!scounter)
                return NULL;
+       name = mono_string_to_utf8_checked (counter, error);
+       return_val_if_nok (error, NULL);
        *type = simple_type_to_type [scounter->type];
-       name = mono_string_to_utf8 (counter);
        inst = custom_get_instance (cat, scounter, name);
        g_free (name);
        if (!inst)
@@ -1331,7 +1319,9 @@ void*
 mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString* instance,
                MonoString* machine, int *type, MonoBoolean *custom)
 {
+       MonoError error;
        const CategoryDesc *cdesc;
+       void *result = NULL;
        /* no support for counters on other machines */
        if (mono_string_compare_ascii (machine, "."))
                return NULL;
@@ -1341,17 +1331,27 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString
                if (!scat)
                        return NULL;
                *custom = TRUE;
-               return custom_get_impl (scat, counter, instance, type);
+               result = custom_get_impl (scat, counter, instance, type, &error);
+               if (mono_error_set_pending_exception (&error))
+                       return NULL;
+               return result;
        }
+       gchar *c_instance = mono_string_to_utf8_checked (instance, &error);
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
        switch (cdesc->id) {
        case CATEGORY_CPU:
-               return cpu_get_impl (counter, instance, type, custom);
+               result = cpu_get_impl (counter, c_instance, type, custom);
+               break;
        case CATEGORY_PROC:
-               return process_get_impl (counter, instance, type, custom);
+               result = process_get_impl (counter, c_instance, type, custom);
+               break;
        case CATEGORY_MONO_MEM:
-               return mono_mem_get_impl (counter, instance, type, custom);
+               result = mono_mem_get_impl (counter, c_instance, type, custom);
+               break;
        case CATEGORY_NETWORK:
-               return network_get_impl (counter, instance, type, custom);
+               result = network_get_impl (counter, c_instance, type, custom);
+               break;
        case CATEGORY_JIT:
        case CATEGORY_EXC:
        case CATEGORY_GC:
@@ -1362,9 +1362,11 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString
        case CATEGORY_SECURITY:
        case CATEGORY_ASPNET:
        case CATEGORY_THREADPOOL:
-               return predef_writable_get_impl (cdesc->id, counter, instance, type, custom);
+               result = predef_writable_get_impl (cdesc->id, counter, c_instance, type, custom);
+               break;
        }
-       return NULL;
+       g_free (c_instance);
+       return result;
 }
 
 MonoBoolean
@@ -1416,10 +1418,14 @@ mono_perfcounter_category_del (MonoString *name)
        return TRUE;
 }
 
+/* this is an icall */
 MonoString*
 mono_perfcounter_category_help (MonoString *category, MonoString *machine)
 {
+       MonoError error;
+       MonoString *result = NULL;
        const CategoryDesc *cdesc;
+       error_init (&error);
        /* no support for counters on other machines */
        if (mono_string_compare_ascii (machine, "."))
                return NULL;
@@ -1428,9 +1434,15 @@ mono_perfcounter_category_help (MonoString *category, MonoString *machine)
                SharedCategory *scat = find_custom_category (category);
                if (!scat)
                        return NULL;
-               return mono_string_new (mono_domain_get (), custom_category_help (scat));
+               result = mono_string_new_checked (mono_domain_get (), custom_category_help (scat), &error);
+               if (mono_error_set_pending_exception (&error))
+                       return NULL;
+               return result;
        }
-       return mono_string_new (mono_domain_get (), cdesc->help);
+       result = mono_string_new_checked (mono_domain_get (), cdesc->help, &error);
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
+       return result;
 }
 
 /*
@@ -1490,7 +1502,6 @@ mono_perfcounter_create (MonoString *category, MonoString *help, int type, MonoA
        SharedCategory *cat;
 
        /* FIXME: ensure there isn't a category created already */
-       mono_error_init (&error);
        name = mono_string_to_utf8_checked (category, &error);
        if (!mono_error_ok (&error))
                goto failure;
@@ -1563,6 +1574,7 @@ failure:
 int
 mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, MonoString *machine)
 {
+       MonoError error;
        const CategoryDesc *cdesc;
        SharedInstance *sinst;
        char *name;
@@ -1576,7 +1588,9 @@ mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, Mo
                scat = find_custom_category (category);
                if (!scat)
                        return FALSE;
-               name = mono_string_to_utf8 (instance);
+               name = mono_string_to_utf8_checked (instance, &error);
+               if (mono_error_set_pending_exception (&error))
+                       return FALSE;
                sinst = find_custom_instance (scat, name);
                g_free (name);
                if (sinst)
@@ -1587,6 +1601,7 @@ mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, Mo
        return FALSE;
 }
 
+/* this is an icall */
 MonoArray*
 mono_perfcounter_category_names (MonoString *machine)
 {
@@ -1611,15 +1626,23 @@ mono_perfcounter_category_names (MonoString *machine)
 
        for (i = 0; i < NUM_CATEGORIES; ++i) {
                const CategoryDesc *cdesc = &predef_categories [i];
-               mono_array_setref (res, i, mono_string_new (domain, cdesc->name));
+               MonoString *name = mono_string_new_checked (domain, cdesc->name, &error);
+               if (!is_ok (&error))
+                       goto leave;
+               mono_array_setref (res, i, name);
        }
        for (tmp = custom_categories; tmp; tmp = tmp->next) {
                SharedCategory *scat = (SharedCategory *)tmp->data;
-               mono_array_setref (res, i, mono_string_new (domain, scat->name));
+               MonoString *name = mono_string_new_checked (domain, scat->name, &error);
+               if (!is_ok (&error))
+                       goto leave;
+               mono_array_setref (res, i, name);
                i++;
        }
+leave:
        perfctr_unlock ();
        g_slist_free (custom_categories);
+       mono_error_set_pending_exception (&error);
        return res;
 }
 
@@ -1645,7 +1668,10 @@ mono_perfcounter_counter_names (MonoString *category, MonoString *machine)
                        return NULL;
                for (i = cdesc->first_counter; i < cdesc [1].first_counter; ++i) {
                        const CounterDesc *desc = &predef_counters [i];
-                       mono_array_setref (res, i - cdesc->first_counter, mono_string_new (domain, desc->name));
+                       MonoString *name = mono_string_new_checked (domain, desc->name, &error);
+                       if (mono_error_set_pending_exception (&error))
+                               return NULL;
+                       mono_array_setref (res, i - cdesc->first_counter, name);
                }
                return res;
        }
@@ -1661,16 +1687,18 @@ mono_perfcounter_counter_names (MonoString *category, MonoString *machine)
                }
 
                for (i = 0; i < scat->num_counters; ++i) {
-                       mono_array_setref (res, i, mono_string_new (domain, p + 1));
+                       MonoString *str = mono_string_new_checked (domain, p + 1, &error);
+                       if (!is_ok (&error))
+                               goto leave;
+                       mono_array_setref (res, i, str);
                        p += 2; /* skip counter type */
                        p += strlen (p) + 1; /* skip counter name */
                        p += strlen (p) + 1; /* skip counter help */
                }
-               perfctr_unlock ();
-               return res;
-       }
+       } else
+               res = mono_array_new_checked (domain, mono_get_string_class (), 0, &error);
+leave:
        perfctr_unlock ();
-       res = mono_array_new_checked (domain, mono_get_string_class (), 0, &error);
        mono_error_set_pending_exception (&error);
        return res;
 }
@@ -1680,7 +1708,7 @@ get_string_array (void **array, int count, gboolean is_process, MonoError *error
 {
        int i;
        MonoDomain *domain = mono_domain_get ();
-       mono_error_init (error);
+       error_init (error);
        MonoArray * res = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), count, error);
        return_val_if_nok (error, NULL);
        for (i = 0; i < count; ++i) {
@@ -1693,9 +1721,11 @@ get_string_array (void **array, int count, gboolean is_process, MonoError *error
                        sprintf (buf, "%d", GPOINTER_TO_INT (array [i]));
                        p = buf;
                }
-               mono_array_setref (res, i, mono_string_new (domain, p));
+               MonoString *str = mono_string_new_checked (domain, p, error);
                if (p != buf)
                        g_free (p);
+               return_val_if_nok (error, NULL);
+               mono_array_setref (res, i, str);
        }
        return res;
 }
@@ -1705,12 +1735,14 @@ get_string_array_of_strings (void **array, int count, MonoError *error)
 {
        int i;
        MonoDomain *domain = mono_domain_get ();
-       mono_error_init (error);
+       error_init (error);
        MonoArray * res = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), count, error);
        return_val_if_nok (error, NULL);
        for (i = 0; i < count; ++i) {
                char* p = (char *)array[i];
-               mono_array_setref (res, i, mono_string_new (domain, p));
+               MonoString *str = mono_string_new_checked (domain, p, error);
+               return_val_if_nok (error, NULL);
+               mono_array_setref (res, i, str);
        }
 
        return res;
@@ -1723,7 +1755,7 @@ get_mono_instances (MonoError *error)
        int res;
        void **buf = NULL;
        MonoArray *array;
-       mono_error_init (error);
+       error_init (error);
        do {
                count *= 2;
                g_free (buf);
@@ -1741,14 +1773,16 @@ get_cpu_instances (MonoError *error)
        void **buf = NULL;
        int i, count;
        MonoArray *array;
-       mono_error_init (error);
+       error_init (error);
        count = mono_cpu_count () + 1; /* +1 for "_Total" */
        buf = g_new (void*, count);
        for (i = 0; i < count; ++i)
                buf [i] = GINT_TO_POINTER (i - 1); /* -1 => _Total */
        array = get_string_array (buf, count, FALSE, error);
        g_free (buf);
-       mono_array_setref (array, 0, mono_string_new (mono_domain_get (), "_Total"));
+       MonoString *total = mono_string_new_checked (mono_domain_get (), "_Total", error);
+       return_val_if_nok (error, NULL);
+       mono_array_setref (array, 0, total);
        return array;
 }
 
@@ -1758,7 +1792,7 @@ get_processes_instances (MonoError *error)
        MonoArray *array;
        int count = 0;
        void **buf = mono_process_list (&count);
-       mono_error_init (error);
+       error_init (error);
        if (!buf)
                return get_string_array (NULL, 0, FALSE, error);
        array = get_string_array (buf, count, TRUE, error);
@@ -1771,7 +1805,7 @@ get_networkinterface_instances (MonoError *error)
 {
        MonoArray *array;
        int count = 0;
-       mono_error_init (error);
+       error_init (error);
        void **buf = mono_networkinterface_list (&count);
        if (!buf)
                return get_string_array_of_strings (NULL, 0, error);
@@ -1784,7 +1818,7 @@ static MonoArray*
 get_custom_instances (MonoString *category, MonoError *error)
 {
        SharedCategory *scat;
-       mono_error_init (error);
+       error_init (error);
        scat = find_custom_category (category);
        if (scat) {
                GSList *list = get_custom_instances_list (scat);
@@ -1797,7 +1831,12 @@ get_custom_instances (MonoString *category, MonoError *error)
                }
                for (tmp = list; tmp; tmp = tmp->next) {
                        SharedInstance *inst = (SharedInstance *)tmp->data;
-                       mono_array_setref (array, i, mono_string_new (mono_domain_get (), inst->instance_name));
+                       MonoString *str = mono_string_new_checked (mono_domain_get (), inst->instance_name, error);
+                       if (!is_ok (error)) {
+                               g_slist_free (list);
+                               return NULL;
+                       }
+                       mono_array_setref (array, i, str);
                        i++;
                }
                g_slist_free (list);