Browse Source

Fail cleanly when MonoPosixHelper.dll version is wrong (bug #35655)

Add version keys to the C and C# versions of Mono.Posix and add static
constructors which fail early if the version keys differ.
Andi McClure 10 years ago
parent
commit
249ee0686b

+ 36 - 0
mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs

@@ -381,6 +381,42 @@ namespace Mono.Unix.Native {
 		internal const string LIBC = "msvcrt";
 		internal const string MPH  = "MonoPosixHelper";
 
+		// It is possible for Mono.Posix and MonoPosixHelper to get out of sync,
+		// for example if NuGet does something weird. To mitigate this, anyone
+		// editing Mono.Posix needs to observe two rules:
+		//   1. When introducing C-interface changes to MonoPosixHelper, update
+		//      the version strings in VersionCheck below and also
+		//      Mono_Unix_VersionString in the C sources.
+		//   2. Any class which performs a DllImport on Stdlib.MPH needs to call
+		//      Stdlib.VersionCheck in its static constructor.
+
+		[DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
+				EntryPoint="Mono_Unix_VersionString")]
+		private static extern IntPtr VersionStringPtr ();
+		private static bool versionCheckPerformed = false;
+		internal static void VersionCheck ()
+		{
+			if (versionCheckPerformed)
+				return;
+
+			// This string is arbitrary; it matters only that it is unique.
+			string assemblyVersion = "MonoProject-2015-12-1";
+			string nativeVersion = Marshal.PtrToStringAnsi (VersionStringPtr ());
+			if (assemblyVersion != nativeVersion)
+			{
+				throw new Exception ("Mono.Posix assembly loaded with a different version (\""
+					+ assemblyVersion + "\") than MonoPosixHelper (\"" + nativeVersion
+				    + "\"). You may need to reinstall Mono.Posix.");
+			}
+
+			versionCheckPerformed = true;
+		}
+
+		static Stdlib ()
+		{
+			VersionCheck ();
+		}
+
 		internal Stdlib () {}
 
 		#region <errno.h> Declarations

+ 5 - 0
mcs/class/Mono.Posix/Mono.Unix/UnixSignal.cs

@@ -39,6 +39,11 @@ namespace Mono.Unix {
 		private int signum;
 		private IntPtr signal_info;
 
+		static UnixSignal ()
+		{
+			Stdlib.VersionCheck ();
+		}
+
 		public UnixSignal (Signum signum)
 		{
 			this.signum = NativeConvert.FromSignum (signum);

+ 1 - 0
support/map.h

@@ -2049,6 +2049,7 @@ int Mono_Posix_Stdlib_clearerr (void* stream);
 void* Mono_Posix_Stdlib_CreateFilePosition (void);
 int Mono_Posix_Stdlib_DumpFilePosition (char* buf, void* handle, int len);
 int Mono_Posix_Stdlib_EOF (void);
+const char* Mono_Unix_VersionString (void);
 int Mono_Posix_Stdlib_EXIT_FAILURE (void);
 int Mono_Posix_Stdlib_EXIT_SUCCESS (void);
 int Mono_Posix_Stdlib_fgetpos (void* stream, void* pos);

+ 7 - 0
support/stdlib.c

@@ -14,6 +14,13 @@
 
 G_BEGIN_DECLS
 
+// See Stdlib.cs
+const char *
+Mono_Unix_VersionString ()
+{
+	return "MonoProject-2015-12-1";
+}
+
 gint32
 Mono_Posix_Stdlib_EXIT_FAILURE (void)
 {