[Mono-devel-list] [patch]Better error reporting when loading unmanaged libraries

Denis Gervalle dgl at softec.st
Thu May 13 08:27:41 EDT 2004


Seems that nobody cares...
So does one of you with write CVS access mind to check this patch in ?
TIA

Denis Gervalle
SOFTEC sa
http://www.softec.st

Denis Gervalle wrote:

> Hello,
>
> Here is a proposed enhancement for error reporting when loading 
> external unmanaged libraries for p-invoke calls. We have written this 
> patch after seaching hard in the dark why a dynamic library next to 
> our mono assembly is presumably not found (DllNotFoundException) by 
> mono. Opposed to Windows that provide an error message box when 
> LoadLibrary cannot properly load a library (usually due to missing 
> dependancies), dlopen do not provide this feature (or misfeature since 
> you cannot have try and choose an alternative without chocking, tries 
> mono DllImportAttribute with a missing library to see successive error 
> message box when it tries to load the library using various names (up 
> to 6)).
>
> Under linux, Mono only trigger the laconic DllNotFoundException 
> followed by the name of the library as provided in the 
> DllImportAttribute when all tries to load the library using various 
> name has failed. It is nearly impossible to know why it has fail and 
> what have been tried.
>
> The attached patch (based on the beta release) modify the triggered 
> exception to provide a larger error message corresponding to the 
> joined error message of all tries done using g_module_open(). Here is 
> an example that tries to load sample.so without success due to a 
> missing dependency from sample.so to libdependency.so.0
>
> Unhandled Exception: System.DllNotFoundException: libsample.so: cannot 
> open shared object file: No such file or directory ==> ./libsample.so: 
> cannot open shared object file: No such file or directory ==> 
> libdependancy.so.0: cannot open shared object file: No such file or 
> directory
>
> From this detailled exception you can see quickly that mono has tried 
> libsample.so and ./libsample.so without success before loading 
> sample.so and failing on its dependency. This is not a perfect error 
> report, but it is really more intuitive than no message at all.
>
> This patch takes care of mint issues and mono pinvoke-wrapper issues. 
> For the latter, each exception messages are allocated permanently on 
> the heap since the exception is triggered by the wrapper code for each 
> call to a function from the missing library (and not during the 
> loading phase). This may be a anoying issue if a program tries lots of 
> missing libraries in a single run (catching exceptions), but there is 
> absolutly no alternative and this is more a theoric issue than a 
> pratical one (Do you often declare lots of static dependencies you do 
> not really need ?). However, this may advocate for a conditional usage 
> of this new feature, but how that could be done is over my current 
> knowledge of mono internals.
> The patch also fix some unrelated compilation warnings in icall.c.
>
> I know that we arrive late for the 1.0 release. Anyway, remember that 
> without this detailed exception, it will be a pain to track down these 
> library issues in large project using a mix of managed and unmanaged 
> libraries.
>
> Hope this helps,
>
> Denis Gervalle
> SOFTEC sa
> http://www.softec.st
>
>------------------------------------------------------------------------
>
>diff -ru mono-0.91-orig/mono/metadata/icall.c mono-0.91/mono/metadata/icall.c
>--- mono-0.91-orig/mono/metadata/icall.c	2004-05-04 21:51:24.000000000 +0200
>+++ mono-0.91/mono/metadata/icall.c	2004-05-05 19:58:49.000000000 +0200
>@@ -4847,6 +4847,7 @@
> 			mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
> 	}
> 	/* create the wrapper, too? */
>+	g_free((gpointer)exc_arg); /* No need to keep the error, no wrapper need it */
> }
> 
> static void
>@@ -4874,13 +4875,13 @@
> 		guint16 **to_lower_data_high, guint16 **to_upper_data_low,
> 		guint16 **to_upper_data_high)
> {
>-	*category_data = CategoryData;
>-	*numeric_data = NumericData;
>-	*numeric_data_values = NumericDataValues;
>-	*to_lower_data_low = ToLowerDataLow;
>-	*to_lower_data_high = ToLowerDataHigh;
>-	*to_upper_data_low = ToUpperDataLow;
>-	*to_upper_data_high = ToUpperDataHigh;
>+	*category_data = (guint8 *)CategoryData;
>+	*numeric_data = (guint8 *)NumericData;
>+	*numeric_data_values = (gdouble *)NumericDataValues;
>+	*to_lower_data_low = (guint16 *)ToLowerDataLow;
>+	*to_lower_data_high = (guint16 *)ToLowerDataHigh;
>+	*to_upper_data_low = (guint16 *)ToUpperDataLow;
>+	*to_upper_data_high = (guint16 *)ToUpperDataHigh;
> }
> 
> /* icall map */
>diff -ru mono-0.91-orig/mono/metadata/loader.c mono-0.91/mono/metadata/loader.c
>--- mono-0.91-orig/mono/metadata/loader.c	2004-04-15 16:51:58.000000000 +0200
>+++ mono-0.91/mono/metadata/loader.c	2004-05-05 19:58:49.000000000 +0200
>@@ -564,6 +564,7 @@
> 	const char *orig_scope;
> 	const char *new_scope;
> 	char *full_name, *file_name;
>+	gchar *error_array[7]={NULL,NULL,NULL,NULL,NULL,NULL,NULL};
> 	int i;
> 	GModule *gmodule = NULL;
> 
>@@ -599,11 +600,12 @@
> 	/*
> 	 * Try loading the module using a variety of names
> 	 */
>-	for (i = 0; i < 2; ++i) {
>+	for (i = 0; i < 6; ) {
> 		if (i == 0)
> 			/* Try the original name */
> 			file_name = g_strdup (new_scope);
> 		else {
>+			error_array[i++] = g_strdup( g_module_error() );
> 			/* Try trimming the .dll extension */
> 			if (strstr (new_scope, ".dll") == (new_scope + strlen (new_scope) - 4)) {
> 				file_name = g_strdup (new_scope);
>@@ -620,12 +622,14 @@
> 		}
> 
> 		if (!gmodule) {
>+			error_array[i++] = g_strdup( g_module_error() );
> 			full_name = g_module_build_path (".", file_name);
> 			gmodule = g_module_open (full_name, G_MODULE_BIND_LAZY);
> 			g_free (full_name);
> 		}
> 
> 		if (!gmodule) {
>+			error_array[i++] = g_strdup( g_module_error() );
> 			gmodule=g_module_open (file_name, G_MODULE_BIND_LAZY);
> 		}
> 
>@@ -635,17 +639,20 @@
> 			break;
> 	}
> 
>-	if (!gmodule) {
>-		gchar *error = g_strdup (g_module_error ());
>-
>-		if (exc_class) {
>-			*exc_class = "DllNotFoundException";
>-			*exc_arg = orig_scope;
>-		}
>-		g_free (error);
>-		return NULL;
>+	if (!gmodule && exc_class) {
>+		*exc_class = "DllNotFoundException";
>+		*exc_arg = g_strjoinv(" ==> ", error_array);
>+		// g_print("LOADER: mono_lookup_pinvoke_call: DllNotFoundException: %s (%x)\n",*exc_arg,*exc_arg);
> 	}
> 
>+	for(i=0; i<6; i++)
>+	    if (error_array[i])
>+		g_free(error_array[i]);
>+	    else
>+		break;
>+	
>+	if (!gmodule) return NULL;
>+
> 	if (piinfo->piflags & PINVOKE_ATTRIBUTE_NO_MANGLE) {
> 		g_module_symbol (gmodule, import, &method->addr); 
> 	} else {
>  
>



More information about the Mono-devel-list mailing list