[runtime] Updates comments.
[mono.git] / mono / utils / mono-error.c
1 /*
2  * mono-error.c: Error handling code
3  *
4  * Authors:
5  *      Rodrigo Kumpera    (rkumpera@novell.com)
6  * Copyright 2009 Novell, Inc (http://www.novell.com)
7  */
8 #include <glib.h>
9
10 #include "mono-error.h"
11 #include "mono-error-internals.h"
12
13 #include <mono/metadata/exception.h>
14 #include <mono/metadata/object-internals.h>
15 #include <mono/metadata/class-internals.h>
16 #include <mono/metadata/debug-helpers.h>
17
18 #define mono_internal_error_get_message(E) ((E)->full_message ? (E)->full_message : (E)->message)
19
20 #define set_error_message() do { \
21         va_list args; \
22         va_start (args, msg_format); \
23         if (g_vsnprintf (error->message, sizeof (error->message), msg_format, args) >= sizeof (error->message)) {\
24                 va_end (args); \
25                 va_start (args, msg_format); \
26                 if (!(error->full_message = g_strdup_vprintf (msg_format, args))) \
27                         error->flags |= MONO_ERROR_INCOMPLETE; \
28         } \
29         va_end (args); \
30 } while (0)
31
32 static void
33 mono_error_prepare (MonoErrorInternal *error)
34 {
35         if (error->error_code != MONO_ERROR_NONE)
36                 return;
37
38         error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = error->full_message_with_fields = NULL;
39         error->klass = NULL;
40         error->message [0] = 0;
41 }
42
43 static const char*
44 get_type_name (MonoErrorInternal *error)
45 {
46         if (error->type_name)
47                 return error->type_name;
48         if (error->klass)
49                 return error->klass->name;
50         return "<unknown type>";
51 }
52
53 static const char*
54 get_assembly_name (MonoErrorInternal *error)
55 {
56         if (error->assembly_name)
57                 return error->assembly_name;
58         if (error->klass && error->klass->image)
59                 return error->klass->image->name;
60         return "<unknown assembly>";
61 }
62
63 void
64 mono_error_init_flags (MonoError *oerror, unsigned short flags)
65 {
66         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
67         g_assert (sizeof (MonoError) == sizeof (MonoErrorInternal));
68
69         error->error_code = MONO_ERROR_NONE;
70         error->flags = flags;
71 }
72
73 void
74 mono_error_init (MonoError *error)
75 {
76         mono_error_init_flags (error, 0);
77 }
78
79 void
80 mono_error_cleanup (MonoError *oerror)
81 {
82         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
83         if (error->error_code == MONO_ERROR_NONE)
84                 return;
85
86         g_free ((char*)error->full_message);
87         g_free ((char*)error->full_message_with_fields);
88         if (!(error->flags & MONO_ERROR_FREE_STRINGS)) //no memory was allocated
89                 return;
90
91         g_free ((char*)error->type_name);
92         g_free ((char*)error->assembly_name);
93         g_free ((char*)error->member_name);
94         g_free ((char*)error->exception_name_space);
95         g_free ((char*)error->exception_name);
96 }
97
98 gboolean
99 mono_error_ok (MonoError *error)
100 {
101         return error->error_code == MONO_ERROR_NONE;
102 }
103
104 unsigned short
105 mono_error_get_error_code (MonoError *error)
106 {
107         return error->error_code;
108 }
109
110 /*Return a pointer to the internal error message, might be NULL.
111 Caller should not release it.*/
112 const char*
113 mono_error_get_message (MonoError *oerror)
114 {
115         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
116         if (error->error_code == MONO_ERROR_NONE)
117                 return NULL;
118         if (error->full_message_with_fields)
119                 return error->full_message_with_fields;
120
121         error->full_message_with_fields = g_strdup_printf ("%s assembly:%s type:%s member:%s",
122                 mono_internal_error_get_message (error),
123                 get_assembly_name (error),
124                 get_type_name (error),
125                 error->member_name ? error->member_name : "<none>");
126
127         return error->full_message_with_fields ? error->full_message_with_fields : mono_internal_error_get_message (error);
128 }
129
130 /*
131  * Inform that this error has heap allocated strings.
132  * The strings will be duplicated if @dup_strings is TRUE
133  * otherwise they will just be free'd in mono_error_cleanup.
134  */
135 void
136 mono_error_dup_strings (MonoError *oerror, gboolean dup_strings)
137 {
138 #define DUP_STR(field) do { if (error->field) {\
139         if (!(error->field = g_strdup (error->field))) \
140                 error->flags |= MONO_ERROR_INCOMPLETE; \
141         }} while (0);
142
143         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
144         error->flags |= MONO_ERROR_FREE_STRINGS;
145
146         if (dup_strings) {
147                 DUP_STR (type_name);
148                 DUP_STR (assembly_name);
149                 DUP_STR (member_name);
150                 DUP_STR (exception_name_space);
151                 DUP_STR (exception_name);
152         }
153 #undef DUP_STR
154 }
155
156 void
157 mono_error_set_error (MonoError *oerror, int error_code, const char *msg_format, ...)
158 {
159         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
160         mono_error_prepare (error);
161
162         error->error_code = error_code;
163         set_error_message ();
164 }
165
166 static void
167 mono_error_set_assembly_name (MonoError *oerror, const char *assembly_name)
168 {
169         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
170         g_assert (error->error_code != MONO_ERROR_NONE);
171
172         error->assembly_name = assembly_name;
173 }
174
175 static void
176 mono_error_set_member_name (MonoError *oerror, const char *member_name)
177 {
178         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
179
180         error->member_name = member_name;
181 }
182
183 static void
184 mono_error_set_type_name (MonoError *oerror, const char *type_name)
185 {
186         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
187
188         error->type_name = type_name;
189 }
190
191 static void
192 mono_error_set_class (MonoError *oerror, MonoClass *klass)
193 {
194         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
195
196         error->klass = klass;   
197 }
198
199 static void
200 mono_error_set_corlib_exception (MonoError *oerror, const char *name_space, const char *name)
201 {
202         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
203
204         error->exception_name_space = name_space;
205         error->exception_name = name;
206 }
207
208
209 void
210 mono_error_set_assembly_load (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
211 {
212         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
213         mono_error_prepare (error);
214
215         error->error_code = MONO_ERROR_FILE_NOT_FOUND;
216         mono_error_set_assembly_name (oerror, assembly_name);
217
218         set_error_message ();
219 }
220
221
222 void
223 mono_error_set_assembly_load_simple (MonoError *oerror, const char *assembly_name, gboolean refection_only)
224 {
225         if (refection_only)
226                 mono_error_set_assembly_load (oerror, assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.");
227         else
228                 mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly or one of its dependencies.");
229 }
230
231 void
232 mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...)
233 {
234         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
235         mono_error_prepare (error);
236
237         error->error_code = MONO_ERROR_TYPE_LOAD;
238         mono_error_set_class (oerror, klass);
239         set_error_message ();
240 }
241
242 /*
243  * Different than other functions, this one here assumes that type_name and assembly_name to have been allocated just for us.
244  * Which means mono_error_cleanup will free them.
245  */
246 void
247 mono_error_set_type_load_name (MonoError *oerror, const char *type_name, const char *assembly_name, const char *msg_format, ...)
248 {
249         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
250         mono_error_prepare (error);
251
252         error->error_code = MONO_ERROR_TYPE_LOAD;
253         mono_error_set_type_name (oerror, type_name);
254         mono_error_set_assembly_name (oerror, assembly_name);
255         mono_error_dup_strings (oerror, FALSE);
256         set_error_message ();
257 }
258
259 void
260 mono_error_set_method_load (MonoError *oerror, MonoClass *klass, const char *method_name, const char *msg_format, ...)
261 {
262         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
263         mono_error_prepare (error);
264
265         error->error_code = MONO_ERROR_MISSING_METHOD;
266         mono_error_set_class (oerror, klass);
267         mono_error_set_member_name (oerror, method_name);
268         set_error_message ();
269 }
270
271 void
272 mono_error_set_field_load (MonoError *oerror, MonoClass *klass, const char *field_name, const char *msg_format, ...)
273 {
274         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
275         mono_error_prepare (error);
276
277         error->error_code = MONO_ERROR_MISSING_FIELD;
278         mono_error_set_class (oerror, klass);
279         mono_error_set_member_name (oerror, field_name);
280         set_error_message ();   
281 }
282
283 void
284 mono_error_set_bad_image_name (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
285 {
286         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
287         mono_error_prepare (error);
288
289         error->error_code = MONO_ERROR_BAD_IMAGE;
290         mono_error_set_assembly_name (oerror, assembly_name);
291         set_error_message ();
292 }
293
294 void
295 mono_error_set_bad_image (MonoError *oerror, MonoImage *image, const char *msg_format, ...)
296 {
297         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
298         mono_error_prepare (error);
299
300         error->error_code = MONO_ERROR_BAD_IMAGE;
301         error->assembly_name = image ? mono_image_get_name (image) : "<no_image>";
302         set_error_message ();
303 }
304
305 void
306 mono_error_set_generic_error (MonoError *oerror, const char * name_space, const char *name, const char *msg_format, ...)
307 {
308         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
309         mono_error_prepare (error);
310
311         error->error_code = MONO_ERROR_GENERIC;
312         mono_error_set_corlib_exception (oerror, name_space, name);
313         set_error_message ();
314 }
315
316 void
317 mono_error_set_from_loader_error (MonoError *oerror)
318 {
319         MonoLoaderError *loader_error = mono_loader_get_last_error ();
320         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
321         gboolean dup_strings = TRUE;
322
323         mono_error_prepare (error);
324
325         if (!loader_error) {
326                 mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce a mono-error from an empty loader-error");
327                 return;
328         }
329
330         switch (loader_error->exception_type) {
331         case MONO_EXCEPTION_NONE:
332                 mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce a mono-error from a non-error loader-error");
333                 break;
334         case MONO_EXCEPTION_SECURITY_LINKDEMAND:
335         case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND:
336                 mono_error_set_generic_error (oerror, "System.Security", "SecurityException", "Failed for unknown reasons.");
337                 break;
338
339         case MONO_EXCEPTION_INVALID_PROGRAM:
340                 mono_error_set_generic_error (oerror, "System", "InvalidProgramException", "Failed for unknown reasons.");
341                 break;
342
343         case MONO_EXCEPTION_UNVERIFIABLE_IL:
344                 mono_error_set_generic_error (oerror, "System.Security", "VerificationException", "Failed for unknown reasons.");
345                 break;
346
347         case MONO_EXCEPTION_MISSING_METHOD:
348                 error->error_code = MONO_ERROR_MISSING_METHOD;
349                 mono_error_set_type_name (oerror, loader_error->class_name);
350                 mono_error_set_member_name (oerror, loader_error->member_name);
351                 g_snprintf (error->message, sizeof (error->message), "Failed for unknown reasons.");
352                 break;
353
354         case MONO_EXCEPTION_MISSING_FIELD:
355                 mono_error_set_field_load (oerror, loader_error->klass, loader_error->member_name, "Failed for unknown reasons.");
356                 break;
357
358         case MONO_EXCEPTION_TYPE_LOAD:
359                 mono_error_set_type_load_name (oerror, g_strdup (loader_error->class_name), g_strdup (loader_error->assembly_name), "Failed for unknown reasons.");
360                 dup_strings = FALSE;
361                 break;
362         
363         case MONO_EXCEPTION_FILE_NOT_FOUND:
364                 mono_error_set_assembly_load_simple (oerror, loader_error->assembly_name, loader_error->ref_only);
365                 break;
366
367         case MONO_EXCEPTION_METHOD_ACCESS:
368                 mono_error_set_generic_error (oerror, "System", "MethodAccessException", "Failed for unknown reasons.");
369                 break;
370
371         case MONO_EXCEPTION_FIELD_ACCESS:
372                 mono_error_set_generic_error (oerror, "System", "FieldAccessException", "Failed for unknown reasons.");
373                 break;
374
375         case MONO_EXCEPTION_OBJECT_SUPPLIED:
376         case MONO_EXCEPTION_GENERIC_SHARING_FAILED:
377                 mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce a mono-error from JIT internal error %d", loader_error->exception_type);
378                 break;
379
380         case MONO_EXCEPTION_BAD_IMAGE:
381                 mono_error_set_bad_image_name (oerror, "<unknown>", "%s", loader_error->msg);
382                 break;
383
384         case MONO_EXCEPTION_OUT_OF_MEMORY:
385                 mono_error_set_out_of_memory (oerror, "Failed for unknown reasons.");
386                 break;
387
388         default:
389                 mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce an unknown loader-error %d", loader_error->exception_type);
390                 break;
391         }
392
393         mono_error_dup_strings (oerror, dup_strings);
394         mono_loader_clear_error ();
395 }
396
397 void
398 mono_loader_set_error_from_mono_error (MonoError *oerror)
399 {
400         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
401
402         switch (error->error_code) {
403         case MONO_ERROR_MISSING_METHOD:
404                 mono_loader_set_error_method_load (get_type_name (error), error->member_name);
405                 break;
406         case MONO_ERROR_MISSING_FIELD:
407                 mono_loader_set_error_field_load (error->klass, error->member_name);
408                 break;
409         case MONO_ERROR_TYPE_LOAD:
410                 mono_loader_set_error_type_load (get_type_name (error), get_assembly_name (error));
411                 break;
412         case MONO_ERROR_FILE_NOT_FOUND:
413                 /* XXX can't recover if it's ref only or not */
414                 mono_loader_set_error_assembly_load (get_assembly_name (error), FALSE);
415                 break;
416         case MONO_ERROR_BAD_IMAGE:
417                 mono_loader_set_error_bad_image (g_strdup (mono_internal_error_get_message (error)));
418                 break;
419         default:
420                 mono_loader_set_error_bad_image (g_strdup_printf ("Non translatable error: %s", mono_internal_error_get_message (error)));
421         }
422 }
423
424 void
425 mono_error_set_out_of_memory (MonoError *oerror, const char *msg_format, ...)
426 {
427         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
428         va_list args;
429         mono_error_prepare (error);
430
431         error->error_code = MONO_ERROR_OUT_OF_MEMORY;
432         va_start (args, msg_format);
433         g_vsnprintf (error->message, sizeof (error->message), msg_format, args);
434         va_end (args);
435 }
436
437 void
438 mono_error_set_argument (MonoError *oerror, const char *argument, const char *msg_format, ...)
439 {
440         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
441         mono_error_prepare (error);
442
443         error->error_code = MONO_ERROR_ARGUMENT;
444         error->type_name = argument; /*use the first available string slot*/
445
446         set_error_message ();
447 }
448
449 void
450 mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...)
451 {
452         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
453         mono_error_prepare (error);
454
455         error->error_code = MONO_ERROR_NOT_VERIFIABLE;
456         if (method) {
457                 mono_error_set_class (oerror, method->klass);
458                 mono_error_set_member_name (oerror, mono_method_full_name (method, 1));
459         }
460
461         set_error_message ();
462 }
463
464
465 static MonoString*
466 get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, MonoError *error_out)
467 {
468         MonoString* res = NULL;
469
470         if (error->type_name) {
471                 res = mono_string_new (domain, error->type_name);
472                 
473         } else if (error->klass) {
474                 char *name = mono_type_full_name (&error->klass->byval_arg);
475                 if (name) {
476                         res = mono_string_new (domain, name);
477                         g_free (name);
478                 }
479         }
480         if (!res)
481                 mono_error_set_out_of_memory (error_out, "Could not allocate type name");
482         return res;
483 }
484
485 static void
486 set_message_on_exception (MonoException *exception, MonoErrorInternal *error, MonoError *error_out)
487 {
488         MonoString *msg = mono_string_new (mono_domain_get (), mono_internal_error_get_message (error));
489         if (msg)
490                 MONO_OBJECT_SETREF (exception, message, msg);
491         else
492                 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
493 }
494
495 /*Can fail with out-of-memory*/
496 MonoException*
497 mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
498 {
499         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
500
501         MonoException* exception = NULL;
502         MonoString *assembly_name = NULL, *type_name = NULL, *method_name = NULL, *field_name = NULL, *msg = NULL;
503         MonoDomain *domain = mono_domain_get ();
504
505         mono_error_init (error_out);
506
507         switch (error->error_code) {
508         case MONO_ERROR_NONE:
509                 return NULL;
510
511         case MONO_ERROR_MISSING_METHOD:
512                 if ((error->type_name || error->klass) && error->member_name) {
513                         type_name = get_type_name_as_mono_string (error, domain, error_out);
514                         if (!mono_error_ok (error_out))
515                                 break;
516
517                         method_name = mono_string_new (domain, error->member_name);
518                         if (!method_name) {
519                                 mono_error_set_out_of_memory (error_out, "Could not allocate method name");
520                                 break;
521                         }
522
523                         exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name);
524                         if (exception)
525                                 set_message_on_exception (exception, error, error_out);
526                 } else {
527                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", mono_internal_error_get_message (error));
528                 }
529                 break;
530
531         case MONO_ERROR_MISSING_FIELD:
532                 if ((error->type_name || error->klass) && error->member_name) {
533                         type_name = get_type_name_as_mono_string (error, domain, error_out);
534                         if (!mono_error_ok (error_out))
535                                 break;
536                         
537                         field_name = mono_string_new (domain, error->member_name);
538                         if (!field_name) {
539                                 mono_error_set_out_of_memory (error_out, "Could not allocate field name");
540                                 break;
541                         }
542                         
543                         exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name);
544                         if (exception)
545                                 set_message_on_exception (exception, error, error_out);
546                 } else {
547                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", mono_internal_error_get_message (error));
548                 }
549                 break;
550
551         case MONO_ERROR_TYPE_LOAD:
552                 if (error->type_name || error->assembly_name) {
553                         type_name = get_type_name_as_mono_string (error, domain, error_out);
554                         if (!mono_error_ok (error_out))
555                                 break;
556
557                         if (error->assembly_name) {
558                                 assembly_name = mono_string_new (domain, error->assembly_name);
559                                 if (!assembly_name) {
560                                         mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
561                                         break;
562                                 }
563                         }
564
565                         exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name);
566                         if (exception)
567                                 set_message_on_exception (exception, error, error_out);
568                 } else {
569                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", mono_internal_error_get_message (error));
570                 }
571                 break;
572
573         case MONO_ERROR_FILE_NOT_FOUND:
574         case MONO_ERROR_BAD_IMAGE:
575                 if (error->assembly_name) {
576                         msg = mono_string_new (domain, mono_internal_error_get_message (error));
577                         if (!msg) {
578                                 mono_error_set_out_of_memory (error_out, "Could not allocate message");
579                                 break;
580                         }
581
582                         if (error->assembly_name) {
583                                 assembly_name = mono_string_new (domain, error->assembly_name);
584                                 if (!assembly_name) {
585                                         mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
586                                         break;
587                                 }
588                         }
589
590                         if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
591                                 exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name);
592                         else
593                                 exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name);
594                 } else {
595                         if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
596                                 exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", mono_internal_error_get_message (error));
597                         else
598                                 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", mono_internal_error_get_message (error));
599                 }
600                 break;
601
602         case MONO_ERROR_OUT_OF_MEMORY:
603                 exception = mono_get_exception_out_of_memory ();
604                 break;
605
606         case MONO_ERROR_ARGUMENT:
607                 exception = mono_get_exception_argument (error->type_name, mono_internal_error_get_message (error));
608                 break;
609
610         case MONO_ERROR_NOT_VERIFIABLE: {
611                 char *type_name = NULL, *message;
612                 if (error->klass) {
613                         type_name = mono_type_get_full_name (error->klass);
614                         if (!type_name) {
615                                 mono_error_set_out_of_memory (error_out, "Could not allocate message");
616                                 break;
617                         }
618                 }
619                 message = g_strdup_printf ("Error in %s:%s %s", type_name, error->member_name, mono_internal_error_get_message (error));
620                 if (!message) {
621                         g_free (type_name);
622                         mono_error_set_out_of_memory (error_out, "Could not allocate message");
623                         break;  
624                 }
625                 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message);
626                 g_free (message);
627                 g_free (type_name);
628                 break;
629         }
630         case MONO_ERROR_GENERIC:
631                 if (!error->exception_name_space || !error->exception_name)
632                         mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "MonoError with generic error but no exception name was supplied");
633                 else
634                         exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, mono_internal_error_get_message (error));
635                 break;
636
637         default:
638                 mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "Invalid error-code %d", error->error_code);
639         }
640
641         if (!mono_error_ok (error_out))
642                 return NULL;
643         if (!exception)
644                 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
645         return exception;
646 }
647
648 /*
649 Convert this MonoError to an exception if it's faulty or return NULL.
650 The error object is cleant after.
651 */
652
653 MonoException*
654 mono_error_convert_to_exception (MonoError *target_error)
655 {
656         MonoError error;
657         MonoException *ex;
658
659         if (mono_error_ok (target_error))
660                 return NULL;
661
662         ex = mono_error_prepare_exception (target_error, &error);
663         if (!mono_error_ok (&error)) {
664                 MonoError second_chance;
665                 /*Try to produce the exception for the second error. FIXME maybe we should log about the original one*/
666                 ex = mono_error_prepare_exception (&error, &second_chance);
667
668                 g_assert (mono_error_ok (&second_chance)); /*We can't reasonable handle double faults, maybe later.*/
669                 mono_error_cleanup (&error);
670         }
671         mono_error_cleanup (target_error);
672         return ex;
673 }
674
675
676 /*
677 Raises the exception of @error.
678 Does nothing if @error has a success error code.
679 Aborts in case of a double fault. This happens when it can't recover from an error caused by trying
680 to construct the first exception object.
681 The error object @error is cleaned up. 
682 */
683 void
684 mono_error_raise_exception (MonoError *target_error)
685 {
686         MonoException *ex = mono_error_convert_to_exception (target_error);
687         if (ex)
688                 mono_raise_exception (ex);      
689 }