[Mono-bugs] [Bug 70429][Maj] Changed - find_method failed in assembly loaded using mono_image_open_from_data from preload_hook

bugzilla-daemon@bugzilla.ximian.com bugzilla-daemon@bugzilla.ximian.com
Tue, 28 Dec 2004 17:20:02 -0500 (EST)


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by ymeng@bloomberg.net.

http://bugzilla.ximian.com/show_bug.cgi?id=70429

--- shadow/70429	2004-12-10 11:41:18.000000000 -0500
+++ shadow/70429.tmp.9795	2004-12-28 17:20:02.000000000 -0500
@@ -1,14 +1,14 @@
 Bug#: 70429
 Product: Mono: Runtime
 Version: 1.1
-OS: 
+OS: unknown
 OS Details: Window XP
 Status: NEW   
 Resolution: 
-Severity: 
+Severity: Unknown
 Priority: Major
 Component: misc
 AssignedTo: mono-bugs@ximian.com                            
 ReportedBy: ymeng@bloomberg.net               
 QAContact: mono-bugs@ximian.com
 TargetMilestone: ---
@@ -280,6 +280,114 @@
               
 }
 
 
 Please consider adding such a function or fix the existing
 image_open_from_data such that it behaves the same as the file based   open
+
+------- Additional Comments From ymeng@bloomberg.net  2004-12-28 17:20 -------
+*** Update ***
+
+The above code causes problem when we tried to load multiple versions 
+of the same-named assembly. In that case the older assembly is always 
+used. The following code fixes the problem:
+
+MonoImage *
+mono_image_open_from_data_with_name(const char *name, char *data, 
+guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status)
+{
+	MonoCLIImageInfo *iinfo;    
+    MonoImage *image, *image2;
+    char *datac;
+    char *imgName;
+    	
+	g_return_val_if_fail (name != NULL, NULL);
+	
+
+	/*
+	 * The easiest solution would be to do all the loading inside 
+the mutex,
+	 * but that would lead to scalability problems. So we let the 
+loading
+	 * happen outside the mutex, and if multiple threads happen 
+to load
+	 * the same image, we discard all but the first copy.
+	 */
+	imgName = g_strdup(name); 
+	
+	EnterCriticalSection (&images_mutex);
+	image = g_hash_table_lookup (loaded_images_hash, imgName);
+	
+	if (image){
+	    if ((image->raw_data_len == data_len) && ( 0==memcmp
+(image->raw_data, data, data_len))){
+		    image->ref_count++;
+		    LeaveCriticalSection (&images_mutex);
+		    return image;
+		}
+		// newer image data is being loaded, close the old 
+image
+		mono_image_close(image);
+		
+	}
+	
+	LeaveCriticalSection (&images_mutex);
+
+
+	if (!data || !data_len) {
+		if (status)
+			*status = MONO_IMAGE_IMAGE_INVALID;
+		return NULL;
+	}
+	datac = data;
+	if (need_copy) {
+		datac = g_try_malloc (data_len);
+		if (!datac) {
+			if (status)
+				*status = MONO_IMAGE_ERROR_ERRNO;
+			return NULL;
+		}
+		memcpy (datac, data, data_len);
+	}
+
+	image = g_new0 (MonoImage, 1);
+	image->ref_count = 1;
+	image->raw_data = datac;
+	image->raw_data_len = data_len;
+	image->raw_data_allocated = need_copy;
+	image->name = imgName;
+	iinfo = g_new0 (MonoCLIImageInfo, 1);
+	image->image_info = iinfo;
+
+
+    image = do_mono_image_load(image, status);
+
+
+	if (image == NULL)
+		return NULL;
+
+	EnterCriticalSection (&images_mutex);
+	image2 = g_hash_table_lookup (loaded_images_hash, image-
+>name);
+
+	if (image2) {
+		/* Somebody else beat us to it */
+		image2->ref_count ++;
+		LeaveCriticalSection (&images_mutex);
+		mono_image_close (image);
+		return image2;
+	}
+	g_hash_table_insert (loaded_images_hash, image->name, image);
+	if (image->assembly_name && (g_hash_table_lookup 
+(loaded_images_hash, image->assembly_name) == NULL))
+		g_hash_table_insert (loaded_images_hash, (char *) 
+image->assembly_name, image);	
+	g_hash_table_insert (loaded_images_guid_hash, image->guid, 
+image);
+	LeaveCriticalSection (&images_mutex);
+
+	return image;
+    
+
+}
+
+