The
.I mcs
compiler is used to compile against the latest Mono Base Class Library
-version and fully implements C# 1.0, 2.0, 3.0 and 4.0 specifications.
+version and fully implements C# 1.0, 2.0, 3.0, 4.0, 5.0 and 6.0
+specifications.
.PP
See the section on packages for more information.
.PP
.TP
.I "Default"
Instruct compiler to use the latest version. Equivalent is to omit the
-switch (this currently defaults to the C# 4.0 language specification).
+switch (this currently defaults to the C# 6.0 language specification).
.TP
.I "ISO-1"
Restrict compiler to use only first ISO standardized features.
Restrict the compiler to use only the features available in C# 4.0
specification.
.TP
+.I "5"
+Restrict the compiler to use only the features available in C# 5.0
+specification.
+.TP
+.I "6"
+Restrict the compiler to use only the features available in C# 6.0
+specification.
+.TP
.I "experimental"
Enables unstable features from upcoming versions of the language.
.PP
Alternative licensing for the compiler is available from Xamarin.
.PP
.SH SEE ALSO
-csharp(1), mdb(1), mono(1), mopen(1), pkg-config(1), sn(1)
+csharp(1), mono(1), pkg-config(1), sn(1)
.PP
.SH BUGS
To report bugs in the compiler, you must file them on our bug tracking
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Mail.MailMessage))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Mail.MailPriority))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Mail.SmtpAccess))]
+#pragma warning disable 618
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Mail.SmtpClient))]
+#pragma warning restore
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Mail.SmtpDeliveryFormat))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Mail.SmtpDeliveryMethod))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Mail.SmtpException))]
System.ServiceModel.Internals \
SMDiagnostics \
System.Numerics \
+ System.Numerics.Vectors \
Mono.Data.Tds \
System.Transactions \
System.EnterpriseServices \
return null;
var c = (HttpHeaderValueCollection<U>) collection;
- if (c.Count == 0)
- return null;
+ if (c.Count == 0) {
+ if (c.InvalidValues == null)
+ return null;
+
+ return new List<string> (c.InvalidValues);
+ }
var list = new List<string> ();
foreach (var item in c) {
list.Add (item.ToString ());
}
+ if (c.InvalidValues != null)
+ list.AddRange (c.InvalidValues);
+
return list;
}
readonly List<T> list;
readonly HttpHeaders headers;
readonly HeaderInfo headerInfo;
+ List<string> invalidValues;
internal HttpHeaderValueCollection (HttpHeaders headers, HeaderInfo headerInfo)
{
}
}
+ internal List<string> InvalidValues {
+ get {
+ return invalidValues;
+ }
+ }
+
public bool IsReadOnly {
get {
return false;
list.AddRange (values);
}
+ internal void AddInvalidValue (string invalidValue)
+ {
+ if (invalidValues == null)
+ invalidValues = new List<string> ();
+
+ invalidValues.Add (invalidValue);
+ }
+
public void Clear ()
{
list.Clear ();
+ invalidValues = null;
}
public bool Contains (T item)
public override string ToString ()
{
- // This implementation prints different values than
- // what .NET does when one of the values is invalid
- // But it better represents what is actually hold by
- // the collection
- return string.Join (headerInfo.Separator, list);
+ var res = string.Join (headerInfo.Separator, list);
+
+ if (invalidValues != null)
+ res += string.Join (headerInfo.Separator, invalidValues);
+
+ return res;
}
public bool TryParseAdd (string input)
headers.Add (name, value);
}
+ var col = (HttpHeaderValueCollection<T>) value.Parsed;
+
if (value.HasStringValues) {
var hinfo = known_headers[name];
- if (value.Parsed == null)
- value.Parsed = hinfo.CreateCollection (this);
+ if (col == null) {
+ value.Parsed = col = new HttpHeaderValueCollection<T> (this, hinfo);
+ }
object pvalue;
for (int i = 0; i < value.Values.Count; ++i) {
- if (!hinfo.TryParse (value.Values[i], out pvalue))
- continue;
-
- hinfo.AddToCollection (value.Parsed, pvalue);
- value.Values.RemoveAt (i);
- --i;
+ var svalue = value.Values[i];
+ if (!hinfo.TryParse (svalue, out pvalue)) {
+ col.AddInvalidValue (svalue);
+ } else {
+ hinfo.AddToCollection (col, pvalue);
+ }
}
+
+ value.Values.Clear ();
}
- return (HttpHeaderValueCollection<T>) value.Parsed;
+ return col;
}
internal void SetValue<T> (string name, T value, Func<object, string> toStringConverter = null)
Assert.AreEqual ("kk, ttt", headers.Connection.ToString (), "#3");
}
+
+ [Test]
+ public void AddInvalid ()
+ {
+ HttpRequestMessage message = new HttpRequestMessage ();
+ HttpRequestHeaders headers = message.Headers;
+
+ headers.TryAddWithoutValidation ("User-Agent", "user,agent/1.0");
+
+ Assert.AreEqual (0, headers.UserAgent.Count, "#1");
+ Assert.AreEqual ("user,agent/1.0", headers.UserAgent.ToString (), "#2");
+
+ Assert.AreEqual ("User-Agent: user,agent/1.0\r\n", headers.ToString (), "#3");
+
+ headers.UserAgent.Clear ();
+ Assert.AreEqual ("", headers.UserAgent.ToString (), "#4");
+ Assert.AreEqual ("", headers.ToString (), "#5");
+ }
+
+ [Test]
+ public void AddInvalidAndValid ()
+ {
+ HttpRequestMessage message = new HttpRequestMessage ();
+ HttpRequestHeaders headers = message.Headers;
+
+ headers.TryAddWithoutValidation ("User-Agent", "user,agent/1.0");
+ headers.TryAddWithoutValidation("User-Agent", "agent2/2.0");
+
+ Assert.AreEqual (1, headers.UserAgent.Count, "#1");
+ Assert.AreEqual ("agent2/2.0user,agent/1.0", headers.UserAgent.ToString (), "#2");
+
+ Assert.AreEqual ("User-Agent: agent2/2.0 user,agent/1.0\r\n", headers.ToString (), "#3");
+
+ headers.UserAgent.Clear ();
+ Assert.AreEqual ("", headers.UserAgent.ToString (), "#4");
+ Assert.AreEqual ("", headers.ToString (), "#5");
+ }
}
}
//
// Author:
// Chris Toshok (toshok@novell.com)
+// Katharina Bogad (bogad@cs.tum.edu)
//
//
using System.Text;
using System.Collections.Specialized;
using System.Security.Permissions;
+using System.Web.Configuration;
namespace System.Web
{
this.name = name;
values = new CookieNVC();
Value = "";
+
+ HttpCookiesSection cookieConfig = (HttpCookiesSection) WebConfigurationManager.GetSection ("system.web/httpCookies");
+
+ if(!string.IsNullOrWhiteSpace(cookieConfig.Domain))
+ domain = cookieConfig.Domain;
+
+ if(cookieConfig.HttpOnlyCookies)
+ flags |= CookieFlags.HttpOnly;
+
+ if(cookieConfig.RequireSSL)
+ flags |= CookieFlags.Secure;
}
public HttpCookie (string name, string value)
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
//
-// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
private IntPtr _readHandle;
private Thread _notifyThread;
private int _lastEntryWritten;
- private bool _notifying;
+ private Object _eventLock = new object();
public Win32EventLog (EventLog coreEventLog)
: base (coreEventLog)
public override void Close ()
{
- if (_readHandle != IntPtr.Zero) {
- CloseEventLog (_readHandle);
- _readHandle = IntPtr.Zero;
+ lock (_eventLock) {
+ if (_readHandle != IntPtr.Zero) {
+ CloseEventLog (_readHandle);
+ _readHandle = IntPtr.Zero;
+ }
}
}
public override void DisableNotification ()
{
- if (_notifyResetEvent != null) {
- _notifyResetEvent.Close ();
- _notifyResetEvent = null;
- }
-
- if (_notifyThread != null) {
- if (_notifyThread.ThreadState == System.Threading.ThreadState.Running)
- _notifyThread.Abort ();
+ lock (_eventLock) {
+ if (_notifyResetEvent != null) {
+ _notifyResetEvent.Close ();
+ _notifyResetEvent = null;
+ }
_notifyThread = null;
}
}
public override void EnableNotification ()
{
- _notifyResetEvent = new ManualResetEvent (false);
- _lastEntryWritten = OldestEventLogEntry + EntryCount;
- if (PInvoke.NotifyChangeEventLog (ReadHandle, _notifyResetEvent.Handle) == 0)
- throw new InvalidOperationException (string.Format (
- CultureInfo.InvariantCulture, "Unable to receive notifications"
- + " for log '{0}' on computer '{1}'.", CoreEventLog.GetLogName (),
- CoreEventLog.MachineName), new Win32Exception ());
- _notifyThread = new Thread (new ThreadStart (NotifyEventThread));
- _notifyThread.IsBackground = true;
- _notifyThread.Start ();
+ lock (_eventLock) {
+ if (_notifyResetEvent != null)
+ return;
+
+ _notifyResetEvent = new ManualResetEvent (false);
+ _lastEntryWritten = OldestEventLogEntry + EntryCount;
+ if (PInvoke.NotifyChangeEventLog (ReadHandle, _notifyResetEvent.Handle) == 0)
+ throw new InvalidOperationException (string.Format (
+ CultureInfo.InvariantCulture, "Unable to receive notifications"
+ + " for log '{0}' on computer '{1}'.", CoreEventLog.GetLogName (),
+ CoreEventLog.MachineName), new Win32Exception ());
+ _notifyThread = new Thread (() => NotifyEventThread(_notifyResetEvent));
+ _notifyThread.IsBackground = true;
+ _notifyThread.Start ();
+ }
}
- private void NotifyEventThread ()
+ private void NotifyEventThread (ManualResetEvent resetEvent)
{
while (true) {
- _notifyResetEvent.WaitOne ();
- lock (this) {
- // after a clear, we something get notified
- // twice for the same entry
- if (_notifying)
- return;
- _notifying = true;
+ try {
+ resetEvent.WaitOne ();
+ } catch (ObjectDisposedException e) {
+ // Notifications have been disabled and event
+ // has been closed but not yet nulled. End thread.
+ break;
}
- try {
+ lock (_eventLock) {
+ if (resetEvent != _notifyResetEvent) {
+ // A new thread has started with another reset event instance
+ // or DisableNotifications has been called, setting
+ // _notifyResetEvent to null. In both cases end this thread.
+ break;
+ }
+
+ if (_readHandle == IntPtr.Zero)
+ break;
+
int oldest_entry = OldestEventLogEntry;
if (_lastEntryWritten < oldest_entry)
_lastEntryWritten = oldest_entry;
CoreEventLog.OnEntryWritten (entry);
}
_lastEntryWritten = last_entry;
- } finally {
- lock (this)
- _notifying = false;
}
}
}
[Test]\r
public void AsyncGetHostByName ()\r
{\r
- IAsyncResult r;\r
- r = Dns.BeginGetHostByName (site1Name, new AsyncCallback (GetHostByNameCallback), null);\r
-\r
IAsyncResult async = Dns.BeginGetHostByName (site1Name, null, null);\r
IPHostEntry entry = Dns.EndGetHostByName (async);\r
SubTestValidIPHostEntry (entry);\r
Assert.IsTrue (entry.HostName == "google-public-dns-a.google.com");\r
}\r
\r
- void GetHostByNameCallback (IAsyncResult ar)\r
- {\r
- IPHostEntry h;\r
- h = Dns.EndGetHostByName (ar);\r
- SubTestValidIPHostEntry (h);\r
+ [Test]\r
+ public void AsyncGetHostByNameCallback ()\r
+ {\r
+ var evt = new ManualResetEvent (false);\r
+ Exception ex = null;\r
+ Dns.BeginGetHostByName (site1Name, new AsyncCallback ((IAsyncResult ar) =>\r
+ {\r
+ try {\r
+ IPHostEntry h;\r
+ h = Dns.EndGetHostByName (ar);\r
+ SubTestValidIPHostEntry (h);\r
+ } catch (Exception e) {\r
+ ex = e;\r
+ } finally {\r
+ evt.Set ();\r
+ }\r
+ }), null);\r
+\r
+ Assert.IsTrue (evt.WaitOne (TimeSpan.FromSeconds (60)), "Wait");\r
+ Assert.IsNull (ex, "Exception");\r
}\r
\r
[Test]\r
public void AsyncResolve ()\r
{\r
- IAsyncResult r;\r
- r = Dns.BeginResolve (site1Name, new AsyncCallback (ResolveCallback), null);\r
-\r
IAsyncResult async = Dns.BeginResolve (site1Dot, null, null);\r
IPHostEntry entry = Dns.EndResolve (async);\r
SubTestValidIPHostEntry (entry);\r
Assert.AreEqual (site1Dot, ip.ToString ());\r
}\r
\r
- void ResolveCallback (IAsyncResult ar)\r
- {\r
- IPHostEntry h = Dns.EndResolve (ar);\r
- SubTestValidIPHostEntry (h);\r
+ [Test]\r
+ public void AsyncResolveCallback ()\r
+ {\r
+ var evt = new ManualResetEvent (false);\r
+ Exception ex = null;\r
+ Dns.BeginResolve (site1Name, new AsyncCallback ((IAsyncResult ar) =>\r
+ {\r
+ try {\r
+ IPHostEntry h = Dns.EndResolve (ar);\r
+ SubTestValidIPHostEntry (h);\r
+ } catch (Exception e) {\r
+ ex = e;\r
+ } finally {\r
+ evt.Set ();\r
+ }\r
+ }), null);\r
+\r
+ Assert.IsTrue (evt.WaitOne (TimeSpan.FromSeconds (60)), "Wait");\r
+ Assert.IsNull (ex, "Exception");\r
}\r
\r
[Test]\r
try {\r
Dns.BeginGetHostAddresses (\r
(string) null,\r
- new AsyncCallback (GetHostAddressesCallback),\r
+ new AsyncCallback (ShouldntBeCalled),\r
null);\r
Assert.Fail ("#1");\r
} catch (ArgumentNullException ex) {\r
try {\r
Dns.BeginGetHostAddresses (\r
"0.0.0.0",\r
- new AsyncCallback (GetHostAddressesCallback),\r
+ new AsyncCallback (ShouldntBeCalled),\r
null);\r
Assert.Fail ("#A1");\r
} catch (ArgumentException ex) {\r
try {\r
Dns.BeginGetHostAddresses (\r
"::0",\r
- new AsyncCallback (GetHostAddressesCallback),\r
+ new AsyncCallback (ShouldntBeCalled),\r
null);\r
Assert.Fail ("#B1");\r
} catch (ArgumentException ex) {\r
}\r
}\r
\r
- void GetHostAddressesCallback (IAsyncResult ar)\r
+ void ShouldntBeCalled (IAsyncResult ar)\r
{\r
- IPAddress [] addresses = Dns.EndGetHostAddresses (ar);\r
- Assert.IsNotNull (addresses);\r
+ Assert.Fail ("Should not be called");\r
}\r
\r
[Test]\r
{\r
try {\r
Dns.BeginResolve ((string) null,\r
- new AsyncCallback (ResolveCallback),\r
+ new AsyncCallback (ShouldntBeCalled),\r
null);\r
Assert.Fail ("#1");\r
} catch (ArgumentNullException ex) {\r
try {\r
Dns.BeginGetHostEntry (\r
(IPAddress) null,\r
- new AsyncCallback (GetHostAddressesCallback),\r
+ new AsyncCallback (ShouldntBeCalled),\r
null);\r
Assert.Fail ("#1");\r
} catch (ArgumentNullException ex) {\r
try {\r
Dns.BeginGetHostEntry (\r
(string) null,\r
- new AsyncCallback (GetHostAddressesCallback),\r
+ new AsyncCallback (ShouldntBeCalled),\r
null);\r
Assert.Fail ("#1");\r
} catch (ArgumentNullException ex) {\r
--- /dev/null
+namespace System.Runtime.Versioning
+{
+ static class BinaryCompatibility
+ {
+ public static readonly bool TargetsAtLeast_Desktop_V4_5 = true;
+ public static readonly bool TargetsAtLeast_Desktop_V4_5_1 = true;
+ }
+}
\ No newline at end of file
{
static class CompatibilitySwitches
{
- public const bool IsAppEarlierThanSilverlight4 = false;
- public const bool IsAppEarlierThanWindowsPhone8 = false;
+ public static readonly bool IsAppEarlierThanSilverlight4 = false;
+ public static readonly bool IsAppEarlierThanWindowsPhone8 = false;
}
}
\ No newline at end of file
internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
{
- bool bNeedSecurityCheck = true;
- bool bCanBeCached = false;
- bool bSecurityCheckOff = false;
+ //bool bNeedSecurityCheck = true;
+ //bool bCanBeCached = false;
+ //bool bSecurityCheckOff = false;
if (!skipCheckThis)
CreateInstanceCheckThis();
- if (!fillCache)
- bSecurityCheckOff = true;
+ //if (!fillCache)
+ // bSecurityCheckOff = true;
return CreateInstanceMono (!publicOnly);
}
WriteEvent (eventId, new object[] { arg1, arg2, arg3 } );
}
+ [CLSCompliant (false)]
protected unsafe void WriteEventCore (int eventId, int eventDataCount, EventData* data)
{
}
{
}
+ [CLSCompliant (false)]
protected unsafe void WriteEventWithRelatedActivityIdCore (int eventId, Guid* relatedActivityId, int eventDataCount, EventSource.EventData* data)
{
}
private StackFrame[] frames;
readonly StackTrace[] captured_traces;
+#pragma warning disable 414
private bool debug_info;
-
- private static Dictionary<string, Func<StackTrace, string>> metadataHandlers;
+#pragma warning restore
[MethodImplAttribute (MethodImplOptions.NoInlining)]
public StackTrace ()
bool AddFrames (StringBuilder sb)
{
- bool printOffset;
string debugInfo, indentation;
string unknown = Locale.GetText ("<unknown method>");
else {
string ret = String.Join (DirectorySeparatorStr, dirs, 0, target);
if (Environment.IsRunningOnWindows) {
+#if !MOBILE
// append leading '\' of the UNC path that was lost in STEP 3.
if (isUnc)
ret = Path.DirectorySeparatorStr + ret;
else
return current + ret;
}
+#endif
} else {
if (root != "" && ret.Length > 0 && ret [0] != '/')
ret = root + ret;
throw new ArgumentException (Locale.GetText ("Path is empty"));
if (path.IndexOfAny (Path.InvalidPathChars) != -1)
throw new ArgumentException (Locale.GetText ("Path contains invalid chars"));
+#if !MOBILE
if (Environment.IsRunningOnWindows) {
int idx = path.IndexOf (':');
if (idx >= 0 && idx != 1)
throw new ArgumentException (parameterName);
}
+#endif
}
internal static string DirectorySeparatorCharAsString {
return new AssemblyBuilder (name, null, access, false);
}
+ public static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access, IEnumerable<CustomAttributeBuilder> assemblyAttributes)
+ {
+ throw new NotImplementedException ();
+ }
+
public ModuleBuilder DefineDynamicModule (string name)
{
return DefineDynamicModule (name, name, false, true);
return res;
}
+ public TypeInfo CreateTypeInfo()
+ {
+ return _tb.CreateTypeInfo ();
+ }
+
public override Type GetEnumUnderlyingType ()
{
return _underlyingType;
internal class UnmanagedMemoryStreamForModule : UnmanagedMemoryStream
{
+#pragma warning disable 414
Module module;
+#pragma warning restore
public unsafe UnmanagedMemoryStreamForModule (byte* pointer, long length, Module module)
: base (pointer, length)
{
}
+#pragma warning disable 67
public event Func<AssemblyLoadContext, System.Reflection.AssemblyName, System.Reflection.Assembly> Resolving;
public event Action<AssemblyLoadContext> Unloading;
+#pragma warning restore
}
}
internal class CADMethodReturnMessage : CADMessageBase {
object _returnValue;
CADArgHolder _exception = null;
+#pragma warning disable 414
Type [] _sig;
+#pragma warning restore
static internal CADMethodReturnMessage Create (IMessage callMsg) {
IMethodReturnMessage msg = callMsg as IMethodReturnMessage;
public abstract class NativeObjectSecurity : CommonObjectSecurity
{
ExceptionFromErrorCode exception_from_error_code;
+#if !MOBILE
ResourceType resource_type;
+#endif
protected internal delegate Exception ExceptionFromErrorCode (int errorCode,
string name, SafeHandle handle,
internal NativeObjectSecurity (CommonSecurityDescriptor securityDescriptor, ResourceType resourceType)
: base (securityDescriptor)
{
+#if !MOBILE
resource_type = resourceType;
+#endif
}
protected NativeObjectSecurity (bool isContainer,
: base (isContainer)
{
exception_from_error_code = exceptionFromErrorCode;
+#if !MOBILE
resource_type = resourceType;
+#endif
}
protected NativeObjectSecurity (bool isContainer,
SetAuditRule((AuditRule)rule);
}
- protected void Persist (SafeHandle handle)
+ protected new void Persist (SafeHandle handle)
{
WriteLock ();
try {
// - SecurityManager.InternalDemand (declarative)
internal void CasOnlyDemand (int skip)
{
+#if !MONO
Assembly current = null;
AppDomain domain = null;
+#endif
if (_ignored == null) {
// special case when directly called from CodeAccessPermission.Demand
static Console ()
{
if (Environment.IsRunningOnWindows) {
+#if !MOBILE
//
// On Windows, follow the Windows tradition
//
-#if MOBILE
- // should never happen since Moonlight does not run on windows
- inputEncoding = outputEncoding = Encoding.Default;
-#else
try {
inputEncoding = Encoding.GetEncoding (WindowsConsole.GetInputCodePage ());
outputEncoding = Encoding.GetEncoding (WindowsConsole.GetOutputCodePage ());
return sign * (hour * 60) * 60;
}
- static TimeZoneInfo defaultZone;
internal static TimeZoneInfo Local {
get {
var id = GetDefaultTimeZoneName ();
- return defaultZone = GetTimeZone (id, id);
+ return GetTimeZone (id, id);
}
}
try {
ret = readlink (path, buf, buf.Length);
- } catch (DllNotFoundException e) {
+ } catch (DllNotFoundException) {
readlinkNotFound = true;
return null;
- } catch (EntryPointNotFoundException e) {
+ } catch (EntryPointNotFoundException) {
readlinkNotFound = true;
return null;
}
} else {
AdjustmentRule first = null, last = null;
+ // Rule start/end dates are either very specific or very broad depending on the platform
+ // 2015-10-04..2016-04-03 - Rule for a time zone in southern hemisphere on non-Windows platforms
+ // 2016-03-27..2016-10-03 - Rule for a time zone in northern hemisphere on non-Windows platforms
+ // 0001-01-01..9999-12-31 - Rule for a time zone on Windows
+
foreach (var rule in GetAdjustmentRules ()) {
- if (rule.DateStart.Year != year && rule.DateEnd.Year != year)
+ if (rule.DateStart.Year > year || rule.DateEnd.Year < year)
continue;
- if (rule.DateStart.Year == year)
+ if (rule.DateStart.Year <= year && (first == null || rule.DateStart.Year > first.DateStart.Year))
first = rule;
- if (rule.DateEnd.Year == year)
+ if (rule.DateEnd.Year >= year && (last == null || rule.DateEnd.Year < last.DateEnd.Year))
last = rule;
}
{\r
public int id;\r
public Mutex mut;\r
+ public bool abandoned_exception;\r
public ConcClass(int id,Mutex mut)\r
{\r
this.id = id;\r
\r
public void WaitAndForget()\r
{\r
- this.Wait();\r
+ try {\r
+ this.Wait();\r
+ } catch (AbandonedMutexException) {\r
+ this.abandoned_exception = true;\r
+ }\r
+\r
this.marker = id;\r
}\r
public void WaitAndWait()\r
}\r
\r
[Test]\r
- public void TestWaitAndFoget1()\r
+ public void TestWaitAndForget1()\r
{\r
Mutex Sem = new Mutex(false);\r
ConcClassLoop class1 = new ConcClassLoop(1,Sem);\r
try {\r
thread1.Start();\r
TestUtil.WaitForNotAlive (thread1, "t1");\r
+ Assert.IsFalse (class1.abandoned_exception, "e1");\r
\r
thread2.Start();\r
TestUtil.WaitForNotAlive (thread2, "t2");\r
+ Assert.IsTrue (class2.abandoned_exception, "e2");\r
\r
Assert.AreEqual (class2.id, class2.marker);\r
} finally {\r
using System;
+using System.Collections.Generic;
using System.Threading;
using NUnit.Framework;
}
}
+ [Test]
+ public void WaitOneWithAbandonedMutex ()
+ {
+ using (var m = new Mutex (false)) {
+ var thread1 = new Thread (() => {
+ m.WaitOne ();
+ });
+ thread1.Start ();
+ thread1.Join (1000);
+ try {
+ m.WaitOne ();
+ Assert.Fail ("Expected AbandonedMutexException");
+ } catch (AbandonedMutexException) {
+ }
+ // Current thread should own the Mutex now
+ var signalled = false;
+ var thread2 = new Thread (() => {
+ signalled = m.WaitOne (100);
+ });
+ thread2.Start ();
+ thread2.Join (1000);
+ Assert.IsFalse (signalled);
+
+ // Since this thread owns the Mutex releasing it shouldn't fail
+ m.ReleaseMutex ();
+ // The Mutex should now be unowned
+ try {
+ m.ReleaseMutex ();
+ Assert.Fail ("Expected ApplicationException");
+ } catch (ApplicationException) {
+ }
+ }
+ }
+
+ [Test]
+ public void WaitOneWithAbandonedMutexAndMultipleThreads ()
+ {
+ using (var m = new Mutex (true)) {
+ var nonAbandoned = 0;
+ var abandoned = 0;
+ var n = 0;
+ var threads = new List<Thread> ();
+ for (int i = 0; i < 50; i++) {
+ var thread = new Thread (() => {
+ try {
+ m.WaitOne ();
+ nonAbandoned++;
+ } catch (AbandonedMutexException) {
+ abandoned++;
+ }
+ if (((n++) % 5) != 0)
+ m.ReleaseMutex ();
+ });
+ thread.Start ();
+ threads.Add (thread);
+ }
+ m.ReleaseMutex ();
+ foreach (var thread in threads) {
+ if (!thread.Join (1000)) {
+ Assert.Fail ("Timed out");
+ }
+ }
+ Assert.AreEqual (40, nonAbandoned);
+ Assert.AreEqual (10, abandoned);
+ }
+ }
+
+ [Test]
+ public void WaitAnyWithSecondMutexAbandoned ()
+ {
+ using (var m1 = new Mutex (false)) {
+ using (var m2 = new Mutex (false)) {
+ var mainProceed = false;
+ var thread2Proceed = false;
+ var thread1 = new Thread (() => {
+ m2.WaitOne ();
+ });
+ var thread2 = new Thread (() => {
+ m1.WaitOne ();
+ mainProceed = true;
+ while (!thread2Proceed) {
+ Thread.Sleep (10);
+ }
+ m1.ReleaseMutex ();
+ });
+ thread1.Start ();
+ thread1.Join (1000);
+ thread2.Start ();
+ while (!mainProceed) {
+ Thread.Sleep (10);
+ }
+ try {
+ WaitHandle.WaitAny (new WaitHandle [] { m1, m2 });
+ Assert.Fail ("Expected AbandonedMutexException");
+ } catch (AbandonedMutexException e) {
+ Assert.AreEqual (1, e.MutexIndex);
+ Assert.AreEqual (m2, e.Mutex);
+ } finally {
+ thread2Proceed = true;
+ thread2.Join (1000);
+ }
+
+ // Current thread should own the second Mutex now
+ var signalled = -1;
+ var thread3 = new Thread (() => {
+ signalled = WaitHandle.WaitAny (new WaitHandle [] { m1, m2 }, 0);
+ });
+ thread3.Start ();
+ thread3.Join (1000);
+ Assert.AreEqual (0, signalled);
+
+ // Since this thread owns the second Mutex releasing it shouldn't fail
+ m2.ReleaseMutex ();
+ // Second Mutex should now be unowned
+ try {
+ m2.ReleaseMutex ();
+ Assert.Fail ("Expected ApplicationException");
+ } catch (ApplicationException) {
+ }
+ // .NET allows the first Mutex which is now abandoned to be released multiple times by this thread
+ m1.ReleaseMutex ();
+ m1.ReleaseMutex ();
+ }
+ }
+ }
+
+ [Test]
+ [ExpectedException (typeof (AbandonedMutexException))]
+ public void WaitAllWithOneAbandonedMutex ()
+ {
+ using (var m1 = new Mutex (false)) {
+ using (var m2 = new Mutex (false)) {
+ var thread = new Thread (() => {
+ m1.WaitOne ();
+ });
+ thread.Start ();
+ thread.Join (1000);
+ WaitHandle.WaitAll (new WaitHandle [] { m1, m2 });
+ }
+ }
+ }
+
#if MONO_FEATURE_THREAD_SUSPEND_RESUME
[Test]
public void WaitOneWithTimeoutAndSpuriousWake ()
[Test]
public void DeltaNotInSeconds ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- throw new ArgumentOutOfRangeException ();;
DateTime dateStart = new DateTime (2007,01,01);
DateTime dateEnd = new DateTime (2008,01,01);
TimeZoneInfo.TransitionTime daylightTransitionStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule (new DateTime (1,1,1,2,0,0), 03, 11);
static FieldInfo cachedDataField;
static object localFieldObj;
+ public static string MapTimeZoneId (string id)
+ {
+ if (Environment.OSVersion.Platform == PlatformID.Unix)
+ return id;
+ else {
+ switch (id) {
+ case "Pacific/Auckland":
+ return "New Zealand Standard Time";
+ case "Europe/Athens":
+ return "GTB Standard Time";
+ case "US/Eastern":
+ return "Eastern Standard Time";
+ case "US/Pacific":
+ return "Pacific Standard Time";
+ case "Australia/Sydney":
+ case "Australia/Melbourne":
+ return "AUS Eastern Standard Time";
+ case "Europe/Brussels":
+ return "Romance Standard Time";
+ case "Africa/Kinshasa":
+ return "W. Central Africa Standard Time";
+ case "Europe/Rome":
+ case "Europe/Vatican":
+ return "W. Europe Standard Time";
+ case "Canada/Eastern":
+ return "Eastern Standard Time";
+ default:
+ Assert.Fail ($"No mapping defined for zone id '{id}'");
+ return null;
+ }
+ }
+ }
+
public static void SetLocal (TimeZoneInfo val)
{
if (localField == null) {
[Test]
public void GetLocal ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
TimeZoneInfo local = TimeZoneInfo.Local;
Assert.IsNotNull (local);
Assert.IsTrue (true);
[Test]
public void DSTInLondon ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
DateTime june01 = new DateTime (2007, 06, 01);
DateTime xmas = new DateTime (2007, 12, 25);
Assert.IsTrue (london.IsDaylightSavingTime (june01), "June 01 is DST in London");
[Test]
public void DSTTransisions ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
DateTime beforeDST = new DateTime (2007, 03, 25, 0, 59, 59, DateTimeKind.Unspecified);
DateTime startDST = new DateTime (2007, 03, 25, 2, 0, 0, DateTimeKind.Unspecified);
DateTime endDST = new DateTime (2007, 10, 28, 1, 59, 59, DateTimeKind.Unspecified);
[Test (Description="Description xambug #17155")]
public void AdjustmentRuleAfterNewYears ()
{
- TimeZoneInfo tz;
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- tz = TimeZoneInfo.FindSystemTimeZoneById ("Pacific/Auckland"); // *nix
- else
- tz = TimeZoneInfo.FindSystemTimeZoneById ("New Zealand Standard Time"); // Windows
-
+ TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Pacific/Auckland"));
// DST start: 9/29/2013 2:00:00 AM
// DST end: 4/6/2014 3:00:00 AM
DateTime dt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Utc);
[Test] //Covers #25050
public void TestAthensDST ()
{
- TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Athens");
+ TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Athens"));
var date = new DateTime (2014, 3, 30 , 2, 0, 0);
Assert.IsFalse (tzi.IsDaylightSavingTime (date));
Assert.AreEqual (new TimeSpan (2,0,0), tzi.GetUtcOffset (date));
// In .NET GetUtcOffset() returns the BaseUtcOffset for times within the hour
// lost when DST starts but IsDaylightSavingTime() returns true.
- TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Athens");
+ TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Athens"));
var date = new DateTime (2014, 3, 30 , 3, 0, 0);
Assert.IsTrue (tzi.IsDaylightSavingTime (date));
[Test] //Covers #41349
public void TestIsDST_DateTimeOffset ()
{
- TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Athens");
+ TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Athens"));
var date = new DateTime (2014, 3, 30 , 2, 0, 0);
var offset = tzi.GetUtcOffset (date);
var dateOffset = new DateTimeOffset (date, offset);
[ExpectedException (typeof (ArgumentException))]
public void ConvertFromUtc_KindIsLocalException ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- throw new ArgumentException ();
TimeZoneInfo.ConvertTimeFromUtc (new DateTime (2007, 5, 3, 11, 8, 0, DateTimeKind.Local), TimeZoneInfo.Local);
}
[Test]
public void ConvertFromUTC_ConvertInWinter ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
DateTime utc = new DateTime (2007, 12, 25, 12, 0, 0);
DateTime converted = TimeZoneInfo.ConvertTimeFromUtc (utc, london);
Assert.AreEqual (utc, converted);
[Test]
public void ConvertFromUtc_ConvertInSummer ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
DateTime utc = new DateTime (2007, 06, 01, 12, 0, 0);
DateTime converted = TimeZoneInfo.ConvertTimeFromUtc (utc, london);
Assert.AreEqual (utc + new TimeSpan (1,0,0), converted);
[ExpectedException (typeof (ArgumentException))]
public void ConvertToUTC_KindIsLocalButSourceIsNot ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- throw new ArgumentException ();
TimeZoneInfo.ConvertTimeToUtc (new DateTime (2007, 5, 3, 12, 8, 0, DateTimeKind.Local), london);
}
[Test]
public void ConvertFromToUtc ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
DateTime utc = DateTime.UtcNow;
Assert.AreEqual (utc.Kind, DateTimeKind.Utc);
DateTime converted = TimeZoneInfo.ConvertTimeFromUtc (utc, london);
[Test]
public void ConvertToTimeZone ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
-
- TimeZoneInfo.ConvertTime (DateTime.Now, TimeZoneInfo.FindSystemTimeZoneById("Pacific/Auckland"));
+ TimeZoneInfo.ConvertTime (DateTime.Now, TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Pacific/Auckland")));
}
[Test]
[Test (Description="Fix for xambug https://bugzilla.xamarin.com/show_bug.cgi?id=17155")]
public void ConvertTime_AdjustmentRuleAfterNewYears ()
{
- TimeZoneInfo tz;
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- tz = TimeZoneInfo.FindSystemTimeZoneById ("Pacific/Auckland"); // *nix
- else
- tz = TimeZoneInfo.FindSystemTimeZoneById ("New Zealand Standard Time"); // Windows
+ TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Pacific/Auckland"));
// DST start: 9/29/2013 2:00:00 AM
// DST end: 4/6/2014 3:00:00 AM
[Test (Description="Fix the bug https://bugzilla.xamarin.com/show_bug.cgi?id=1849")]
public void ConvertTime_AjustmentConvertTimeWithSourceTimeZone () {
- TimeZoneInfo easternTimeZone;
- TimeZoneInfo pacificTimeZone;
-
- if (Environment.OSVersion.Platform == PlatformID.Unix) {
- // *nix
- easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById ("US/Eastern");
- pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById ("US/Pacific");
- }
- else {
- // Windows
- easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById ("Eastern Standard Time");
- pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById ("Pacific Standard Time");
- }
+ TimeZoneInfo easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("US/Eastern"));
+ TimeZoneInfo pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("US/Pacific"));
DateTime lastMidnight = new DateTime (new DateTime (2012, 06, 13).Ticks, DateTimeKind.Unspecified);
DateTime lastMidnightAsEST = TimeZoneInfo.ConvertTime (lastMidnight, pacificTimeZone, easternTimeZone);
[Test]
public void AmbiguousDates ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
Assert.IsFalse (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 1, 0, 0)));
Assert.IsTrue (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 1, 0, 1)));
Assert.IsTrue (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 2, 0, 0)));
[Test]
public void AmbiguousUTCDates ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
Assert.IsFalse (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 0, 0, 0, DateTimeKind.Utc)));
Assert.IsTrue (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 0, 0, 1, DateTimeKind.Utc)));
Assert.IsTrue (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 0, 59, 59, DateTimeKind.Utc)));
[Test]
public void NotEmpty ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
global::System.Collections.ObjectModel.ReadOnlyCollection<TimeZoneInfo> systemTZ = TimeZoneInfo.GetSystemTimeZones ();
Assert.IsNotNull(systemTZ, "SystemTZ is null");
Assert.IsFalse (systemTZ.Count == 0, "SystemTZ is empty");
[Test]
public void ContainsBrussels ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
global::System.Collections.ObjectModel.ReadOnlyCollection<TimeZoneInfo> systemTZ = TimeZoneInfo.GetSystemTimeZones ();
foreach (TimeZoneInfo tz in systemTZ) {
- if (tz.Id == "Europe/Brussels")
+ if (tz.Id == MapTimeZoneId ("Europe/Brussels"))
return;
}
Assert.Fail ("Europe/Brussels not found in SystemTZ");
[ExpectedException (typeof (TimeZoneNotFoundException))]
public void NonSystemTimezone ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- throw new TimeZoneNotFoundException ();
TimeZoneInfo.FindSystemTimeZoneById ("Neverland/The_Lagoon");
}
[Test]
public void FindBrusselsTZ ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
- TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
+ TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Brussels"));
Assert.IsNotNull (brussels);
}
[Test]
public void OffsetIsCorrectInKinshasa ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
- TimeZoneInfo kin = TimeZoneInfo.FindSystemTimeZoneById ("Africa/Kinshasa");
+ TimeZoneInfo kin = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Africa/Kinshasa"));
Assert.AreEqual (new TimeSpan (1,0,0), kin.BaseUtcOffset, "BaseUtcOffset in Kinshasa is not +1h");
}
[Test]
public void OffsetIsCorrectInBrussels ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
- TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
+ TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Brussels"));
Assert.AreEqual (new TimeSpan (1,0,0), brussels.BaseUtcOffset, "BaseUtcOffset for Brussels is not +1h");
}
[Test]
public void NoDSTInKinshasa ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
- TimeZoneInfo kin = TimeZoneInfo.FindSystemTimeZoneById ("Africa/Kinshasa");
+ TimeZoneInfo kin = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Africa/Kinshasa"));
Assert.IsFalse (kin.SupportsDaylightSavingTime);
}
[Test]
public void BrusselsSupportsDST ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
- TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
+ TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Brussels"));
Assert.IsTrue (brussels.SupportsDaylightSavingTime);
}
[Test]
public void MelbourneSupportsDST ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
- TimeZoneInfo melbourne = TimeZoneInfo.FindSystemTimeZoneById ("Australia/Melbourne");
+ TimeZoneInfo melbourne = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Australia/Melbourne"));
Assert.IsTrue (melbourne.SupportsDaylightSavingTime);
}
[Test]
public void RomeAndVaticanSharesTime ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
- TimeZoneInfo rome = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Rome");
- TimeZoneInfo vatican = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Vatican");
+ TimeZoneInfo rome = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Rome"));
+ TimeZoneInfo vatican = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Vatican"));
Assert.IsTrue (rome.HasSameRules (vatican));
}
[ExpectedException (typeof(ArgumentException))]
public void DateIsNotAmbiguous ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- throw new ArgumentException ();
- TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
+ TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Brussels"));
DateTime date = new DateTime (2007, 05, 11, 11, 40, 00);
brussels.GetAmbiguousTimeOffsets (date);
}
[Test]
public void AmbiguousOffsets ()
{
- if (Environment.OSVersion.Platform != PlatformID.Unix)
- Assert.Ignore ("Not running on Unix.");
- TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
+ TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Brussels"));
DateTime date = new DateTime (2007, 10, 28, 2, 30, 00);
Assert.IsTrue (brussels.IsAmbiguousTime (date));
Assert.AreEqual (2, brussels.GetAmbiguousTimeOffsets (date).Length);
[Test]
public void TestSydneyDaylightChanges ()
{
- TimeZoneInfo tz;
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- tz = TimeZoneInfo.FindSystemTimeZoneById ("Australia/Sydney");
- else
- tz = TimeZoneInfo.FindSystemTimeZoneById ("W. Australia Standard Time");
+ TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Australia/Sydney"));
var changes = (DaylightTime) getChanges.Invoke (tz, new object [] {2014});
Assert.AreEqual (new DateTime (2014, 4, 6, 3, 0, 0), changes.End);
}
+ [Test]
+ public void TestAthensDaylightChanges ()
+ {
+ TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Athens"));
+
+ var changes = (DaylightTime) getChanges.Invoke (tz, new object [] {2014});
+
+ Assert.AreEqual (new TimeSpan (1, 0, 0), changes.Delta);
+ Assert.AreEqual (new DateTime (2014, 3, 30, 3, 0, 0), changes.Start);
+ Assert.AreEqual (new DateTime (2014, 10, 26, 4, 0, 0), changes.End);
+ }
+
[Test]
public void AllTimeZonesDaylightChanges ()
{
private void CET (TimeZone t1)
{
- Assert.AreEqual("CET", t1.StandardName, "A01");
- Assert.AreEqual("CEST", t1.DaylightName, "A02");
+ Assert.IsTrue("CET" == t1.StandardName || "W. Europe Standard Time" == t1.StandardName, "A01");
+ Assert.IsTrue("CEST" == t1.DaylightName || "W. Europe Daylight Time" == t1.DaylightName, "A02");
DaylightTime d1 = t1.GetDaylightChanges (2002);
Assert.AreEqual("03/31/2002 02:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "A03");
private void EST (TimeZone t1)
{
- // It could be EST though...
- //Assert.AreEqual("Eastern Standard Time", t1.StandardName, "B01");
- //Assert.AreEqual("Eastern Daylight Time", t1.DaylightName, "B02");
+ Assert.IsTrue("EST" == t1.StandardName || "Eastern Standard Time" == t1.StandardName, "B01");
+ Assert.IsTrue("EDT" == t1.DaylightName || "Eastern Daylight Time" == t1.DaylightName, "B02");
DaylightTime d1 = t1.GetDaylightChanges (2002);
Assert.AreEqual("04/07/2002 02:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "B03");
{
TimeZone t1 = TimeZone.CurrentTimeZone;
switch (t1.StandardName) {
+ case "W. Europe Standard Time":
case "CET":
CET (t1);
break;
[Test]
public void FindSystemTimeZoneById ()
{
- TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById ("Canada/Eastern");
- Assert.AreEqual ("EDT", tzi.DaylightName, "DaylightName");
- Assert.AreEqual ("EST", tzi.StandardName, "StandardName");
+ TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (TimeZoneInfoTest.MapTimeZoneId ("Canada/Eastern"));
+ Assert.IsTrue ("EDT" == tzi.DaylightName || "Eastern Daylight Time" == tzi.DaylightName, "DaylightName");
+ Assert.IsTrue ("EST" == tzi.StandardName || "Eastern Standard Time" == tzi.StandardName, "StandardName");
Assert.IsTrue (tzi.SupportsDaylightSavingTime, "SupportsDaylightSavingTime");
}
#endif
const string ASSEMBLY_NAME = "MonoTests.System.TypeTest";
static int typeIndexer = 0;
+ static bool isMono = Type.GetType ("Mono.Runtime", false) != null;
[SetUp]
public void SetUp ()
Assert.AreEqual (t1.FullName, "System.__ComObject");
- if (Environment.OSVersion.Platform == PlatformID.Win32Windows ||
- Environment.OSVersion.Platform == PlatformID.Win32NT)
+ if (!isMono && (Environment.OSVersion.Platform == PlatformID.Win32Windows ||
+ Environment.OSVersion.Platform == PlatformID.Win32NT))
Activator.CreateInstance(t1);
Assert.AreEqual (t2.FullName, "System.__ComObject");
ReferenceSources/SharedStatics.cs
ReferenceSources/SecurityContext.cs
ReferenceSources/PathInternal.cs
+ReferenceSources/BinaryCompatibility.cs
../referencesource/mscorlib/system/__filters.cs
../referencesource/mscorlib/system/__hresults.cs
../referencesource/mscorlib/system/runtime/serialization/formatters/soapfault.cs
../referencesource/mscorlib/system/runtime/serialization/formatters/soapmessage.cs
-../referencesource/mscorlib/system/runtime/versioning/binarycompatibility.cs
../referencesource/mscorlib/system/runtime/versioning/componentguaranteesattribute.cs
../referencesource/mscorlib/system/runtime/versioning/multitargetinghelpers.cs
../referencesource/mscorlib/system/runtime/versioning/NonVersionableAttribute.cs
, IComparable<Boolean>, IEquatable<Boolean>
#endif
{
-
+#pragma warning disable 649
//
// Member Variables
//
private bool m_value;
+#pragma warning disable
// The true value.
//
Contract.EndContractBlock();
if (count > 0) {
+#if !MONO
int i = _size;
+#endif
_size -= count;
if (index < _size) {
Array.Copy(_items, index + count, _items, index, _size - index);
Byte[] decodedBytes = new Byte[resultLength];
// Convert Base64 chars into bytes:
- Int32 actualResultLength;
fixed (Byte* decodedBytesPtr = decodedBytes)
- actualResultLength = FromBase64_Decode(inputPtr, inputLength, decodedBytesPtr, resultLength);
+ FromBase64_Decode(inputPtr, inputLength, decodedBytesPtr, resultLength);
// Note that actualResultLength can differ from resultLength if the caller is modifying the array
// as it is being converted. Silently ignore the failure.
internal const int UNICODE_CATEGORY_OFFSET = 0;
internal const int BIDI_CATEGORY_OFFSET = 1;
+#pragma warning disable 414
static bool s_initialized = InitTable();
+#pragma warning restore
// The native pointer to the 12:4:4 index table of the Unicode cateogry data.
[SecurityCritical]
[NonSerialized]
private String m_sortName; // The name that defines our behavior
+#if !MONO
[NonSerialized]
private IntPtr m_dataHandle;
[NonSerialized]
private IntPtr m_handleOrigin;
+#endif
////////////////////////////////////////////////////////////////////////
//
// the following fields are defined to keep the compatibility with Whidbey.
// don't change/remove the names/types of these fields.
#if FEATURE_USE_LCID || MONO
+#pragma warning disable 169
[OptionalField(VersionAdded = 1)]
private int win32LCID; // mapped sort culture id of this instance
+#pragma warning restore
private int culture; // the culture ID used to create this instance.
#endif
[OnDeserializing]
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
}
+
+#if !MONO
byte[] keyData = null;
+#endif
// The OS doesn't have quite the same behavior so we have to test for empty inputs
if (String.IsNullOrEmpty(source))
{
+#if !MONO
// Empty strings get an empty sort key
keyData = EmptyArray<Byte>.Value;
+#endif
// Fake value to test though so we can verify our flags
source = "\x0000";
}
[OptionalField(VersionAdded = 1)]
private bool m_useUserOverride;
#if !FEATURE_CORECLR
+#pragma warning disable 169
[OptionalField(VersionAdded = 1)]
private bool bUseCalendarInfo;
[OptionalField(VersionAdded = 1)]
internal bool m_isDefaultCalendar; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey)
[OptionalField(VersionAdded = 2)]
private static volatile Hashtable s_calendarNativeNames; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey)
+#pragma warning restore
#endif // !FEATURE_CORECLR
// This was synthesized by Whidbey so we knew what words might appear in the middle of a date string
ClearTokenHashTable();
}
}
-
+#if !MONO
// Whitespaces that we allow in the month names.
// U+00a0 is non-breaking space.
static char[] MonthSpaces = {' ', '\u00a0'};
+#endif
internal bool HasSpacesInMonthNames {
get {
parseInfo.fAllowInnerWhite = ((styles & DateTimeStyles.AllowInnerWhite) != 0);
parseInfo.fAllowTrailingWhite = ((styles & DateTimeStyles.AllowTrailingWhite) != 0);
+#if !MONO
// We need the original values of the following two below.
String originalFormat = formatParam;
+#endif
if (formatParam.Length == 1) {
if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParam[0] == 'U') {
[System.Security.SecuritySafeCritical] // auto-generated
private static EraInfo[] GetErasFromRegistry()
{
+#if MONO
+ return null;
+#else
// Look in the registry key and see if we can find any ranges
int iFoundEras = 0;
EraInfo[] registryEraRanges = null;
-#if !MONO
+
try
{
// Need to access registry
registryEraRanges[i].maxEraYear = registryEraRanges[i-1].yearOffset + 1 - registryEraRanges[i].yearOffset;
}
}
-#endif
+
// Return our ranges
return registryEraRanges;
+#endif
}
//
m_NlsVersion = nlsVersion;
if(customVersion == Guid.Empty) {
+#if !MONO
byte[] b = BitConverter.GetBytes(effectiveId);
+#endif
byte b1 = (byte) ((uint) effectiveId >> 24);
byte b2 = (byte) ((effectiveId & 0x00FF0000) >> 16);
byte b3 = (byte) ((effectiveId & 0x0000FF00) >> 8);
// put in InternalReadChars.
int charsRead = 0;
int numBytes = 0;
- long posSav = posSav = 0;
+ long posSav = 0;
if (m_stream.CanSeek)
posSav = m_stream.Position;
[System.Security.SecuritySafeCritical]
get
{
+#pragma warning disable 219
String demandDir;
+#pragma warning restore
if (this is DirectoryInfo)
demandDir = Directory.GetDemandDir(FullPath, true);
else
[System.Security.SecurityCritical]
get
{
+#pragma warning disable 219
String demandDir;
+#pragma warning restore
if (this is DirectoryInfo)
demandDir = Directory.GetDemandDir(FullPath, true);
else
// This information isn't guaranteed to be correct, but is our second
// best effort at a file or directory involved, after the exception
// message.
+#pragma warning disable 414
[NonSerialized]
private String _maybeFullPath; // For debuggers on partial trust code
+#pragma warning restore
public IOException()
: base(Environment.GetResourceString("Arg_IOException")) {
// write any buffered data to those streams even during finalization, which
// is generally the right thing to do.
if (stream != null) {
+#pragma warning disable 184
// Note: flush on the underlying stream can throw (ex., low disk space)
if (disposing || (LeaveOpen && stream is __ConsoleStream))
{
+#pragma warning restore
#if FEATURE_ASYNC_IO
CheckAsyncTaskInProgress();
#endif
// Jun 08: for cases other than ACCESS_DENIED, we'll assert instead of throw to give release builds more opportunity to fallback.
//
-
+#pragma warning disable 168
catch (FileLoadException fle)
+#pragma warning restore
{
#if !MONO
// Ignore cases where the loader gets an access
private bool UseManifest; // Use Assembly manifest, or grovel disk.
+#pragma warning disable 414
// unused! But need to keep for serialization
[OptionalField(VersionAdded = 1)]
private bool UseSatelliteAssem; // Are all the .resources files in the
// main assembly, or in satellite assemblies for each culture?
+#pragma warning restore
#if RESOURCE_SATELLITE_CONFIG
private static volatile Hashtable _installedSatelliteInfo; // Give the user the option
// to prevent certain satellite assembly probes via a config file.
// My private debugging aid. Set to 5 or 6 for verbose output. Set to 3
// for summary level information.
internal static readonly int DEBUG = 0; //Making this const causes C# to consider all of the code that it guards unreachable.
-
+#if FEATURE_APPX
private static volatile bool s_IsAppXModel;
+#endif
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
private void Init()
#region Non-TransparentProxy case
if (name == null)
throw new ArgumentNullException("name");
-
+#if MONO
+ throw new NotImplementedException ();
+#else
bool[] isByRef = modifiers == null ? null : modifiers[0].IsByRefArray;
// pass LCID_ENGLISH_US if no explicit culture is specified to match the behavior of VB
int lcid = (culture == null ? 0x0409 : culture.LCID);
-#if MONO
- throw new NotImplementedException ();
-#else
return InvokeDispMethod(name, bindingFlags, target, providedArgs, isByRef, lcid, namedParams);
#endif
#endregion
if (binder == null)
binder = DefaultBinder;
+#if !MONO
bool bDefaultBinder = (binder == DefaultBinder);
+#endif
#endregion
#region Delegate to Activator.CreateInstance
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
internal sealed class TypeDependencyAttribute: Attribute
{
-
+#pragma warning disable 414
private string typeName;
+#pragma warning restore
public TypeDependencyAttribute (string typeName)
{
{
// Private members that will hold the relevant details.
private Exception m_Exception;
+#if !MONO
private string m_remoteStackTrace;
+#endif
private object m_stackTrace;
+#if !MONO
private object m_dynamicMethods;
private UIntPtr m_IPForWatsonBuckets;
private Object m_WatsonBuckets;
+#endif
private ExceptionDispatchInfo(Exception exception)
{
#endif
}
+#if !MONO
internal UIntPtr IPForWatsonBuckets
{
get
return m_WatsonBuckets;
}
}
+#endif
internal object BinaryStackTraceArray
{
}
}
+#if !MONO
internal object DynamicMethodArray
{
get
return m_remoteStackTrace;
}
}
+#endif
// This static method is used to create an instance of ExceptionDispatchInfo for
// the specified exception object and save all the required details that maybe
internal sealed class BinaryMethodCall
{
+#if FEATURE_REMOTING
String uri;
+#endif
String methodName;
String typeName;
+#if FEATURE_REMOTING
Type[] instArgs;
+#endif
Object[] args;
+#if FEATURE_REMOTING
Object methodSignature;
+#endif
Object callContext;
+#if FEATURE_REMOTING
String scallContext;
Object properties;
+#endif
Type[] argTypes;
bool bArgsPrimitive = true;
MessageEnum messageEnum;
// if not the args are written out as a separate array
internal Object[] WriteArray(String uri, String methodName, String typeName, Type[] instArgs, Object[] args, Object methodSignature, Object callContext, Object[] properties)
{
+#if FEATURE_REMOTING
this.uri = uri;
+#endif
this.methodName = methodName;
this.typeName = typeName;
+#if FEATURE_REMOTING
this.instArgs = instArgs;
+#endif
this.args = args;
+#if FEATURE_REMOTING
this.methodSignature = methodSignature;
+#endif
this.callContext = callContext;
+#if FEATURE_REMOTING
this.properties = properties;
+#endif
int arraySize = 0;
if (args == null || args.Length == 0)
{
if (callContext is String)
BinaryUtil.NVTraceI("callContext", (String)callContext);
+#if FEATURE_REMOTING
else
BinaryUtil.NVTraceI("callContext", scallContext);
+#endif
}
if (IOUtil.FlagTest(messageEnum, MessageEnum.ArgsInline))
{
Object returnValue;
Object[] args;
+#if FEATURE_REMOTING
Exception exception;
+#endif
Object callContext;
+#if FEATURE_REMOTING
String scallContext;
Object properties;
+#endif
Type[] argTypes;
bool bArgsPrimitive = true;
MessageEnum messageEnum;
this.returnValue = returnValue;
this.args = args;
+#if FEATURE_REMOTING
this.exception = exception;
+#endif
this.callContext = callContext;
+#if FEATURE_REMOTING
this.properties = properties;
+#endif
int arraySize = 0;
if (args == null || args.Length == 0)
{
if (callContext is String)
BinaryUtil.NVTraceI("callContext", (String)callContext);
+#if FEATURE_REMOTING
else
BinaryUtil.NVTraceI("callContext", scallContext);
+#endif
}
if (IOUtil.FlagTest(messageEnum, MessageEnum.ArgsInline))
}
internal BinaryObjectString binaryObjectString;
+#if !MONO
internal BinaryCrossAppDomainString binaryCrossAppDomainString;
+#endif
internal void WriteObjectString(int objectId, String value)
{
private void WriteArrayAsBytes(Array array, int typeLength)
{
InternalWriteItemNull();
+#if !MONO
int byteLength = array.Length*typeLength;
+#endif
int arrayOffset = 0;
if (byteBuffer == null)
byteBuffer = new byte[chunkSize];
internal BinaryAssembly binaryAssembly;
+#if !MONO
internal BinaryCrossAppDomainAssembly crossAppDomainAssembly;
+#endif
internal void WriteAssembly(Type type, String assemblyString, int assemId, bool isNew)
{
[Serializable]
internal sealed class BinaryMethodCallMessage
{
+#pragma warning disable 414
Object[] _inargs = null;
+#pragma warning restore
String _methodName = null;
String _typeName = null;
Object _methodSignature = null;
[Serializable]
internal class BinaryMethodReturnMessage
{
+#pragma warning disable 414
Object[] _outargs = null;
+#pragma warning restore
Exception _exception = null;
Object _returnValue = null;
internal Object m_topObject;
internal Header[] headers;
internal HeaderHandler handler;
+#pragma warning disable 649
internal SerObjectInfoInit serObjectInfoInit;
+#pragma warning restore
internal IFormatterConverter m_formatterConverter;
// Stack of Object ParseRecords
{
SerTrace.Log( this, "ParseArray Entry");
+#if !MONO
long genId = pr.PRobjectId;
+#endif
if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)
{
ParseRecord objectPr = (ParseRecord)stack.Peek();
+#if !MONO
String objName = null;
if (objectPr != null)
objName = objectPr.PRname;
+#endif
#if _DEBUG
SerTrace.Log( this, "ParseMember ",objectPr.PRobjectId," ",pr.PRname);
TypeInformation typeInfo = BinaryFormatter.GetTypeInformation(resolvedType);
if (typeInfo.HasTypeForwardedFrom)
{
+#pragma warning disable 219
Assembly typeFowardedFromAssembly = null;
+#pragma warning restore
try
{
// if this Assembly.Load failed, we still want to throw security exception
{
for (int i=0; i<Count(); i++)
{
+#if _DEBUG
Object obj = objects[i];
-#if _DEBUG
SerTrace.Log(this, "Stack Dump ",stackId," "+((obj is ITrace)?((ITrace)obj).Trace():""));
#endif
}
internal long m_fixupCount;
internal ISurrogateSelector m_selector;
internal StreamingContext m_context;
+#if !FEATURE_PAL
bool m_isCrossAppDomain;
+#endif
[System.Security.SecuritySafeCritical] // auto-generated
public ObjectManager(ISurrogateSelector selector, StreamingContext context) : this(selector, context, true, false) {
m_objects = new ObjectHolder[DefaultInitialSize];
m_selector = selector;
m_context = context;
+#if !FEATURE_PAL
m_isCrossAppDomain = isCrossAppDomain;
+#endif
}
int[] arrayIndex = null;
ValueTypeFixupInfo currFixup=null;
Object fixupObj=holder.ObjectValue;
+#if false
ObjectHolder originalHolder = holder;
+#endif
Contract.Assert(holder!=null, "[TypedReferenceBuilder.ctor]holder!=null");
Contract.Assert(holder.RequiresValueTypeFixup, "[TypedReferenceBuilder.ctor]holder.RequiresValueTypeFixup");
// Traverse the hierarchy to find all methods with the particular attribute
while (baseType != null && baseType != typeof(Object))
{
+#if !MONO
RuntimeType rt = (RuntimeType)baseType;
+#endif
// Get all methods which are declared on this type, instance and public or nonpublic
MethodInfo[] mis = baseType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
#if _DEBUG
// Invoke all OnSerializingMethods
if (m_OnSerializingMethods != null)
{
+#if !MONO
Object[] p = new Object[] {context};
+#endif
SerializationEventHandler handler = null;
foreach(MethodInfo m in m_OnSerializingMethods)
{
// Invoke all OnDeserializingMethods
if (m_OnDeserializingMethods != null)
{
+#if !MONO
Object[] p = new Object[] {context};
+#endif
SerializationEventHandler handler = null;
foreach(MethodInfo m in m_OnDeserializingMethods)
{
// Invoke all OnDeserializingMethods
if (m_OnDeserializedMethods != null)
{
+#if !MONO
Object[] p = new Object[] {context};
+#endif
SerializationEventHandler handler = null;
foreach(MethodInfo m in m_OnDeserializedMethods)
{
switch (enumerator.Name)
{
case VersionKey:
- string version = info.GetString(VersionKey);
+ info.GetString(VersionKey);
break;
case AuthenticationTypeKey:
private string _hashName;
private byte[] _password;
private HashAlgorithm _hash;
+#if !MONO
private CspParameters _cspParams;
-#if !MONO
+
[System.Security.SecurityCritical] // auto-generated
private SafeProvHandle _safeProvHandle = null;
private SafeProvHandle ProvHandle {
this.Salt = salt;
this.HashName = hashName;
_password = password;
+#if !MONO
_cspParams = cspParams;
+#endif
}
//
private byte[] m_salt;
private HMACSHA1 m_hmacsha1; // The pseudo-random generator function used in PBKDF2
private byte[] m_password;
+#if !MONO
private CspParameters m_cspParams = new CspParameters();
+#endif
private uint m_iterations;
private uint m_block;
using System.Security.Permissions;
using System.Diagnostics.Contracts;
+#if !MONO
// Object layout of the RSAParameters structure
internal class RSACspObject {
internal byte[] Exponent;
internal byte[] InverseQ;
internal byte[] D;
}
+#endif
[System.Runtime.InteropServices.ComVisible(true)]
public sealed partial class RSACryptoServiceProvider : RSA
}
while (true) {
+#if !MONO
int p = pos;
int i = pos;
+#endif
while (pos < len) {
ch = format[pos];
StringBuilder fmt = null;
if (ch == ':') {
pos++;
+#if !MONO
p = pos;
i = pos;
+#endif
while (true) {
if (pos == len) FormatError();
ch = format[pos];
if (newValue == null)
newValue = "";
+#if !MONO
int deltaLength = newValue.Length - oldValue.Length;
+#endif
int[] replacements = null; // A list of replacement positions in a chunk to apply
int replacementsCount = 0;
{
// Replacing mutates the blocks, so we need to convert to logical index and back afterward.
int index = indexInChunk + chunk.m_ChunkOffset;
+#if !MONO
int indexBeforeAdjustment = index;
+#endif
// See if we accumulated any replacements, if so apply them
ReplaceAllInChunk(replacements, replacementsCount, chunk, oldValue.Length, newValue);
/// <typeparam name="T">The kind of elements contained within.</typeparam>
internal class SparselyPopulatedArray<T> where T : class
{
+#if DEBUG
private readonly SparselyPopulatedArrayFragment<T> m_head;
+#endif
private volatile SparselyPopulatedArrayFragment<T> m_tail;
/// <summary>
/// <param name="initialSize">How many array slots to pre-allocate.</param>
internal SparselyPopulatedArray(int initialSize)
{
- m_head = m_tail = new SparselyPopulatedArrayFragment<T>(initialSize);
+#if DEBUG
+ m_head =
+#endif
+ m_tail = new SparselyPopulatedArrayFragment<T>(initialSize);
}
#if DEBUG
else
{
//This is the original 4.0 behaviour
- var asyncResult = beginMethod(iar =>
+ beginMethod(iar =>
{
FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
}, state);
else
{
//quirk for previous versions
- var asyncResult = beginMethod(arg1, iar =>
+ beginMethod(arg1, iar =>
{
FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
}, state);
else
{
//quirk for previous versions
- var asyncResult = beginMethod(arg1, arg2, iar =>
+ beginMethod(arg1, arg2, iar =>
{
FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
}, state);
else
{
//quirk for previous versions
- var asyncResult = beginMethod(arg1, arg2, arg3, iar =>
+ beginMethod(arg1, arg2, arg3, iar =>
{
FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
}, state);
get { return m_cancellationToken; }
set
{
+#if !MONO
if (value == null)
throw new ArgumentNullException("CancellationToken");
+#endif
m_cancellationToken = value;
}
}
}
}
+#if !MONO
// ETW event for Parallel Invoke Begin
int forkJoinContextID = 0;
Task callerTask = null;
-#if !MONO
+
if (TplEtwProvider.Log.IsEnabled())
{
forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
}, null);
}
+#if !MONO
// ETW event for Parallel For begin
int forkJoinContextID = 0;
Task callingTask = null;
-#if !MONO
+
if (TplEtwProvider.Log.IsEnabled())
{
forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
}, null);
}
+#if !MONO
// ETW event for Parallel For begin
Task callerTask = null;
int forkJoinContextID = 0;
-#if !MONO
+
if (TplEtwProvider.Log.IsEnabled())
{
forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
/// </summary>
internal class ParallelLoopStateFlags
{
+#pragma warning disable 649
internal static int PLS_NONE;
+#pragma warning restore
internal static int PLS_EXCEPTIONAL = 1;
internal static int PLS_BROKEN = 2;
internal static int PLS_STOPPED = 4;
{
oldState = m_LoopStateFlags;
if ((oldState & illegalStates) != 0) return false;
+#pragma warning disable 420
if (Interlocked.CompareExchange(ref m_LoopStateFlags, oldState | newState, oldState) == oldState)
+#pragma warning restore
{
return true;
}
/// <summary>The action to invoke.</summary>
protected readonly Action m_action;
+#if !MONO
protected int m_continuationId;
+#endif
/// <summary>Initializes the continuation.</summary>
/// <param name="action">The action to invoke. Must not be null.</param>
throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong",name));
}
Contract.EndContractBlock();
- Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
#if !MONO
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+
#if FEATURE_MACL
// For ACL's, get the security descriptor from the EventWaitHandleSecurity.
if (eventSecurity != null) {
// The head and tail of the queue. We enqueue to the head, and dequeue from the tail.
internal volatile QueueSegment queueHead;
internal volatile QueueSegment queueTail;
+#if !MONO
internal bool loggingEnabled;
+#endif
internal static SparseArray<WorkStealingQueue> allThreadQueues = new SparseArray<WorkStealingQueue>(16); //
public struct TypedReference
{
#if MONO
+#pragma warning disable 169
RuntimeTypeHandle type;
+#pragma warning restore
#endif
private IntPtr Value;
private IntPtr Type;
--- /dev/null
+// CS0029: Cannot implicitly convert type `string' to `int'
+// Line: 8
+
+class A<T> where T : CB, IA
+{
+ void Foo (T t)
+ {
+ t.Prop = "3";
+ }
+}
+
+class CB : CA
+{
+}
+
+class CA
+{
+ public int Prop { get; set; }
+}
+
+interface IA
+{
+ string Prop { get; set; }
+}
\ No newline at end of file
--- /dev/null
+// CS0122: `A.Y' is inaccessible due to its protection level
+// Line: 8
+
+public class Test
+{
+ public static void Main ()
+ {
+ var x = nameof (A.Y);
+ }
+}
+
+public class A
+{
+ private int Y { get; set; }
+}
\ No newline at end of file
--- /dev/null
+// CS0619: `A.X' is obsolete: `'
+// Line: 10
+
+using System;
+
+public class Test
+{
+ public static void Main()
+ {
+ var m = nameof (A.X);
+ }
+}
+
+public class A
+{
+ [Obsolete ("", true)]
+ public int X;
+}
--- /dev/null
+// CS1070: The type `C' has been forwarded to an assembly that is not referenced. Consider adding a reference to assembly `CS1070-lib-missing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
+// Line: 5
+// Compiler options: -r:CS1070-lib.dll
+
+public class D
+{
+ static void Main ()
+ {
+ new C ();
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS1501: No overload for method `Call' takes `0' arguments
+// Line: 8
+
+class A<T> where T : CB, IA
+{
+ void Foo (T t)
+ {
+ t.Call ();
+ }
+}
+
+class CB : CA
+{
+}
+
+class CA
+{
+ public void Call (int arg)
+ {
+ }
+}
+
+interface IA
+{
+ void Call (bool arg, int arg2);
+}
this.name = name;
}
- static void Error_MethodGroupWithTypeArguments (ResolveContext rc, Location loc)
- {
- rc.Report.Error (8084, loc, "An argument to nameof operator cannot be method group with type arguments");
- }
-
protected override Expression DoResolve (ResolveContext rc)
{
throw new NotSupportedException ();
rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator");
var res = sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity | MemberLookupRestrictions.NameOfExcluded);
- if (sn.HasTypeArguments && res is MethodGroupExpr) {
- Error_MethodGroupWithTypeArguments (rc, expr.Location);
- }
+ var me = res as MemberExpr;
+ if (me != null)
+ me.ResolveNameOf (rc, sn);
return true;
}
return false;
}
- var mg = res as MethodGroupExpr;
- if (mg != null) {
- var emg = res as ExtensionMethodGroupExpr;
- if (emg != null && !emg.ResolveNameOf (rc, ma)) {
- return true;
- }
-
- if (!mg.HasAccessibleCandidate (rc)) {
- ErrorIsInaccesible (rc, ma.GetSignatureForError (), loc);
- }
-
- if (ma.HasTypeArguments) {
- Error_MethodGroupWithTypeArguments (rc, ma.Location);
- }
+ var me = res as MemberExpr;
+ if (me != null) {
+ me.ResolveNameOf (rc, ma);
}
//
public static Expression MemberLookup (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
{
var members = MemberCache.FindMembers (queried_type, name, false);
- if (members == null)
- return null;
- Expression expr;
- do {
- expr = MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
- if (expr != null)
- return expr;
+ if (members != null) {
+ Expression expr;
+ do {
+ expr = MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
+ if (expr != null)
+ return expr;
- if (members [0].DeclaringType.BaseType == null)
- members = null;
- else
- members = MemberCache.FindMembers (members [0].DeclaringType.BaseType, name, false);
- } while (members != null);
+ if (members [0].DeclaringType.BaseType == null)
+ members = null;
+ else
+ members = MemberCache.FindMembers (members [0].DeclaringType.BaseType, name, false);
+ } while (members != null);
+ }
+
+ var tps = queried_type as TypeParameterSpec;
+ if (tps != null) {
+ members = MemberCache.FindInterfaceMembers (tps, name);
+ if (members != null)
+ return MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
+ }
- return expr;
+ return null;
}
public static Expression MemberLookupToExpression (IMemberContext rc, IList<MemberSpec> members, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
if (member is MethodSpec) {
- //
- // Interface members that are hidden by class members are removed from the set. This
- // step only has an effect if T is a type parameter and T has both an effective base
- // class other than object and a non-empty effective interface set
- //
- var tps = queried_type as TypeParameterSpec;
- if (tps != null && tps.HasTypeConstraint)
- members = RemoveHiddenTypeParameterMethods (members);
-
return new MethodGroupExpr (members, queried_type, loc);
}
return null;
}
- static IList<MemberSpec> RemoveHiddenTypeParameterMethods (IList<MemberSpec> members)
- {
- if (members.Count < 2)
- return members;
-
- //
- // If M is a method, then all non-method members declared in an interface declaration
- // are removed from the set, and all methods with the same signature as M declared in
- // an interface declaration are removed from the set
- //
-
- bool copied = false;
- for (int i = 0; i < members.Count; ++i) {
- var method = members[i] as MethodSpec;
- if (method == null) {
- if (!copied) {
- copied = true;
- members = new List<MemberSpec> (members);
- }
-
- members.RemoveAt (i--);
- continue;
- }
-
- if (!method.DeclaringType.IsInterface)
- continue;
-
- for (int ii = 0; ii < members.Count; ++ii) {
- var candidate = members[ii] as MethodSpec;
- if (candidate == null || !candidate.DeclaringType.IsClass)
- continue;
-
- if (!TypeSpecComparer.Override.IsEqual (candidate.Parameters, method.Parameters))
- continue;
-
- if (!AParametersCollection.HasSameParameterDefaults (candidate.Parameters, method.Parameters))
- continue;
-
- if (!copied) {
- copied = true;
- members = new List<MemberSpec> (members);
- }
-
- members.RemoveAt (i--);
- break;
- }
- }
-
- return members;
- }
-
protected static void Error_NamedArgument (NamedArgument na, Report Report)
{
Report.Error (1742, na.Location, "An element access expression cannot use named argument");
return this;
}
+ public virtual void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+ {
+
+ }
+
protected void EmitInstance (EmitContext ec, bool prepare_for_load)
{
var inst = new InstanceEmitter (InstanceExpression, TypeSpec.IsValueType (InstanceExpression.Type));
// For extension methodgroup we are not looking for base members but parent
// namespace extension methods
//
- public override IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+ public override IList<MemberSpec> GetBaseMembers (TypeSpec type)
{
// TODO: candidates are null only when doing error reporting, that's
// incorrect. We have to discover same extension methods in error mode
Convert.ImplicitBoxingConversion (null, argType, extensionType) != null;
}
- public bool ResolveNameOf (ResolveContext rc, MemberAccess ma)
+ public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
{
- rc.Report.Error (8093, ma.Location, "An argument to nameof operator cannot be extension method group");
-
- // Not included in C#6
- /*
- ExtensionExpression = ExtensionExpression.Resolve (rc);
- if (ExtensionExpression == null)
- return false;
-
- var argType = ExtensionExpression.Type;
- foreach (MethodSpec candidate in Candidates) {
- if (ExtensionMethodGroupExpr.IsExtensionTypeCompatible (argType, candidate.Parameters.ExtensionMethodType))
- return true;
- }
-
- // TODO: Scan full hierarchy
-
- ma.Error_TypeDoesNotContainDefinition (rc, argType, ma.Name);
- */
- return false;
+ rc.Report.Error (8093, expr.Location, "An argument to nameof operator cannot be extension method group");
}
public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
return base.ResolveMemberAccess (ec, left, original);
}
+ public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+ {
+ if (!HasAccessibleCandidate (rc)) {
+ ErrorIsInaccesible (rc, expr.GetSignatureForError (), loc);
+ }
+
+ if (expr.HasTypeArguments) {
+ rc.Report.Error (8084, expr.Location, "An argument to nameof operator cannot be method group with type arguments");
+ }
+ }
+
public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
{
type_arguments = ta;
#region IBaseMembersProvider Members
- public virtual IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+ public virtual IList<MemberSpec> GetBaseMembers (TypeSpec type)
{
- return baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
+ var baseType = type.BaseType;
+
+ IList<MemberSpec> members = baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
+
+ if (members == null && !type.IsInterface) {
+ var tps = queried_type as TypeParameterSpec;
+ if (tps != null)
+ members = MemberCache.FindInterfaceMembers (tps, Methods [0].Name);
+ }
+
+ return members;
}
public IParametersMember GetOverrideMemberParameters (MemberSpec member)
// Restore expanded arguments
candidate_args = args;
}
- } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null);
+ } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType)) != null);
//
// We've found exact match
return constant.GetSignatureForError ();
}
+ public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+ {
+ constant.CheckObsoleteness (rc, expr.Location);
+ }
+
public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
{
Error_TypeArgumentsCannotBeUsed (ec, "constant", GetSignatureForError (), loc);
return this;
}
+ public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+ {
+ spec.CheckObsoleteness (rc, expr.Location);
+ }
+
public void SetFieldAssigned (FlowAnalysisContext fc)
{
if (!IsInstance)
return true;
}
+ public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+ {
+ if (!best_candidate.IsAccessible (rc))
+ ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), expr.Location);
+
+ best_candidate.CheckObsoleteness (rc, expr.Location);
+ }
+
public void SetBackingFieldAssigned (FlowAnalysisContext fc)
{
if (backing_field != null) {
return TypeManager.CSharpSignature (spec);
}
+ public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+ {
+ spec.CheckObsoleteness (rc, expr.Location);
+ }
+
public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
{
Error_TypeArgumentsCannotBeUsed (ec, "event", GetSignatureForError (), loc);
#region IBaseMembersProvider Members
- IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec baseType)
+ IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec type)
{
- return baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false);
+ var baseType = type.BaseType;
+ var members = baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false);
+
+ if (members == null && !type.IsInterface) {
+ var tps = queried_type as TypeParameterSpec;
+ if (tps != null)
+ members = MemberCache.FindInterfaceMembers (tps, MemberCache.IndexerNameAlias);
+ }
+
+ return members;
}
IParametersMember OverloadResolver.IBaseMembersProvider.GetOverrideMemberParameters (MemberSpec member)
TypeSpec[] targs;
TypeSpec[] ifaces_defined;
TypeSpec effective_base;
+ MemberCache interface_cache;
//
// Creates type owned type parameter
}
}
+ public MemberCache InterfaceCache {
+ get {
+ return interface_cache;
+ }
+ }
+
//
// Unexpanded interfaces list
//
// For a type parameter the membercache is the union of the sets of members of the types
// specified as a primary constraint or secondary constraint
//
+ bool has_user_base_type = false;
if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) {
cache.AddBaseType (BaseType);
+ has_user_base_type = true;
}
if (InterfacesDefined != null) {
+ var icache = cache;
+ if (has_user_base_type) {
+ //
+ // type-parameter lookup rules are more complicated that other types lookup rules.
+ // Effective base class and its base types member have priority over interface
+ // constraints which means we cannot lookup interface members before class members
+ // hence we setup secondary cache for such cases.
+ //
+ interface_cache = new MemberCache ();
+ icache = interface_cache;
+ }
+
foreach (var iface_type in InterfacesDefined) {
- cache.AddInterface (iface_type);
+ icache.AddInterface (iface_type);
}
}
var ifaces = tps == null ? ta.Interfaces : tps.InterfacesDefined;
if (ifaces != null) {
+ var icache = cache;
+ if (has_user_base_type) {
+ interface_cache = new MemberCache ();
+ icache = interface_cache;
+ }
+
foreach (var iface_type in ifaces) {
- cache.AddInterface (iface_type);
+ icache.AddInterface (iface_type);
}
}
}
public static MemberSpec FindMember (TypeSpec container, MemberFilter filter, BindingRestriction restrictions)
{
+ if (filter.Kind == MemberKind.Method && container.Kind == MemberKind.TypeParameter && filter.Parameters == null)
+ throw new NotSupportedException ("type parameters methods cannot be lookup up due to two stage setup");
+
+ IList<MemberSpec> applicable;
+ var top_container = container;
+
do {
- IList<MemberSpec> applicable;
if (container.MemberCache.member_hash.TryGetValue (filter.Name, out applicable)) {
// Start from the end because interface members are in reverse order
for (int i = applicable.Count - 1; i >= 0; i--) {
container = container.BaseType;
} while (container != null);
+ var tps = top_container as TypeParameterSpec;
+ if (tps != null && tps.InterfaceCache != null) {
+ if (tps.InterfaceCache.member_hash.TryGetValue (filter.Name, out applicable)) {
+ for (int i = applicable.Count - 1; i >= 0; i--) {
+ var entry = applicable [i];
+
+ if ((restrictions & BindingRestriction.NoAccessors) != 0 && entry.IsAccessor)
+ continue;
+
+ if ((restrictions & BindingRestriction.OverrideOnly) != 0 && (entry.Modifiers & Modifiers.OVERRIDE) == 0)
+ continue;
+
+ if (!filter.Equals (entry))
+ continue;
+
+ return entry;
+ }
+ }
+ }
+
return null;
}
//
public static IList<MemberSpec> FindMembers (TypeSpec container, string name, bool declaredOnlyClass)
{
- IList<MemberSpec> applicable;
-
do {
+ IList<MemberSpec> applicable;
+
if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnlyClass)
return applicable;
return null;
}
+ public static IList<MemberSpec> FindInterfaceMembers (TypeParameterSpec typeParameter, string name)
+ {
+ if (typeParameter.InterfaceCache != null) {
+ IList<MemberSpec> applicable;
+ typeParameter.InterfaceCache.member_hash.TryGetValue (name, out applicable);
+ return applicable;
+ }
+
+ return null;
+ }
+
//
// Finds the nested type in container
//
var imported = MemberDefinition as ImportedTypeDefinition;
if (imported != null && Kind != MemberKind.MissingType)
imported.DefineInterfaces (this);
-
}
return ifaces;
public TypeSpec Element { get; private set; }
+ public override IList<TypeSpec> Interfaces {
+ set {
+ throw new NotSupportedException ();
+ }
+ }
+
bool ITypeDefinition.IsComImport {
get {
return false;
readonly int rank;
readonly ModuleContainer module;
- private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
+ ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
: base (MemberKind.ArrayType, element, null)
{
this.module = module;
this.rank = rank;
}
+ public override IList<TypeSpec> Interfaces {
+ get {
+ return BaseType.Interfaces;
+ }
+ }
+
public int Rank {
get {
return rank;
if (!module.ArrayTypesCache.TryGetValue (key, out ac)) {
ac = new ArrayContainer (module, element, rank);
ac.BaseType = module.Compiler.BuiltinTypes.Array;
- ac.Interfaces = ac.BaseType.Interfaces;
module.ArrayTypesCache.Add (key, ac);
}
class ReferenceContainer : ElementTypeSpec
{
- private ReferenceContainer (TypeSpec element)
+ ReferenceContainer (TypeSpec element)
: base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
{
}
+ public override IList<TypeSpec> Interfaces {
+ get {
+ return null;
+ }
+ }
+
public override MetaType GetMetaInfo ()
{
if (info == null) {
state &= ~StateFlags.CLSCompliant_Undetected;
}
+ public override IList<TypeSpec> Interfaces {
+ get {
+ return null;
+ }
+ }
+
public override MetaType GetMetaInfo ()
{
if (info == null) {
--- /dev/null
+class A<T> where T : CB, IA
+{
+ void Foo (T t)
+ {
+ t.Prop = 3;
+ long l = t.Prop2;
+ t["1"] = "2";
+ }
+}
+
+class A2<T, U>
+ where T : CB, U
+ where U : IA
+{
+ void Foo (T t)
+ {
+ t.Prop = 3;
+ long l = t.Prop2;
+ t["1"] = "2";
+ }
+}
+
+class CB : CA
+{
+}
+
+class CA
+{
+ public int Prop { get; set; }
+
+ public string this [byte b] { get { return ""; } }
+}
+
+interface IA
+{
+ string Prop { get; set; }
+ long Prop2 { get; }
+
+ string this [string b] { get; set; }
+}
+
+class X
+{
+ public static void Main ()
+ {
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="gtest-639.cs">
+ <type name="A`1[T]">
+ <method name="Void Foo(T)" attrs="129">
+ <size>53</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="CB">
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="CA">
+ <method name="Int32 get_Prop()" attrs="2182">
+ <size>14</size>
+ </method>
+ <method name="Void set_Prop(Int32)" attrs="2182">
+ <size>8</size>
+ </method>
+ <method name="System.String get_Item(Byte)" attrs="2182">
+ <size>14</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X">
+ <method name="Void Main()" attrs="150">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="A2`2[T,U]">
+ <method name="Void Foo(T)" attrs="129">
+ <size>53</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-anontype-01.cs">
<type name="Test">
<method name="Int32 Main()" attrs="150">
ret = mono_w32handle_wait_one (handle, timeout, alertable);
if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0)
return WAIT_OBJECT_0;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_ABANDONED_0)
+ return WAIT_ABANDONED_0;
else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED)
return WAIT_IO_COMPLETION;
else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT)
ret = mono_w32handle_signal_and_wait (signal_handle, wait, timeout, alertable);
if (ret == MONO_W32HANDLE_WAIT_RET_SUCCESS_0)
return WAIT_OBJECT_0;
+ else if (ret == MONO_W32HANDLE_WAIT_RET_ABANDONED_0)
+ return WAIT_ABANDONED_0;
else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED)
return WAIT_IO_COMPLETION;
else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT)
MonoW32HandleWaitRet ret;
ret = mono_w32handle_wait_multiple (handles, numobjects, waitall, timeout, alertable);
- if (ret >= MONO_W32HANDLE_WAIT_RET_SUCCESS_0)
+ if (ret >= MONO_W32HANDLE_WAIT_RET_SUCCESS_0 && ret <= MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + numobjects - 1)
return WAIT_OBJECT_0 + (ret - MONO_W32HANDLE_WAIT_RET_SUCCESS_0);
+ else if (ret >= MONO_W32HANDLE_WAIT_RET_ABANDONED_0 && ret <= MONO_W32HANDLE_WAIT_RET_ABANDONED_0 + numobjects - 1)
+ return WAIT_ABANDONED_0 + (ret - MONO_W32HANDLE_WAIT_RET_ABANDONED_0);
else if (ret == MONO_W32HANDLE_WAIT_RET_ALERTED)
return WAIT_IO_COMPLETION;
else if (ret == MONO_W32HANDLE_WAIT_RET_TIMEOUT)
handle.c \
handle.h \
w32mutex.h \
+ w32mutex-utils.h \
w32semaphore.h \
w32event.h \
w32handle-namespace.h \
#include <mono/metadata/tokentype.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/abi-details.h>
#include <mono/utils/mono-uri.h>
#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/mono-path.h>
int version = mono_get_corlib_version ();
if (version != MONO_CORLIB_VERSION)
return g_strdup_printf ("expected corlib version %d, found %d.", MONO_CORLIB_VERSION, version);
- else
- return NULL;
+
+ /* Check that the managed and unmanaged layout of MonoInternalThread matches */
+ guint32 native_offset = (guint32) MONO_STRUCT_OFFSET (MonoInternalThread, last);
+ guint32 managed_offset = mono_field_get_offset (mono_class_get_field_from_name (mono_defaults.internal_thread_class, "last"));
+ if (native_offset != managed_offset)
+ return g_strdup_printf ("expected InternalThread.last field offset %u, found %u. See InternalThread.last comment", native_offset, managed_offset);
+
+ return NULL;
}
/**
return NULL;
}
-static gboolean
-prevent_running_reference_assembly (MonoAssembly *ass, MonoError *error)
-{
- mono_error_init (error);
- gboolean refasm = mono_assembly_get_reference_assembly_attribute (ass, error);
- if (!is_ok (error))
- return TRUE;
- if (refasm) {
- mono_error_set_bad_image (error, ass->image, "Could not load file or assembly or one of its dependencies. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context.\n");
- return TRUE;
- }
- return FALSE;
-}
-
MonoReflectionAssembly *
ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean refOnly)
{
MonoDomain *domain = mono_domain_get ();
char *name, *filename;
MonoImageOpenStatus status = MONO_IMAGE_OK;
- MonoAssembly *ass = NULL;
-
- name = NULL;
- result = NULL;
-
- mono_error_init (&error);
+ MonoAssembly *ass;
if (fname == NULL) {
- mono_error_set_argument_null (&error, "assemblyFile", "");
- goto leave;
+ MonoException *exc = mono_get_exception_argument_null ("assemblyFile");
+ mono_set_pending_exception (exc);
+ return NULL;
}
name = filename = mono_string_to_utf8_checked (fname, &error);
- if (!is_ok (&error))
- goto leave;
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
ass = mono_assembly_open_full (filename, &status, refOnly);
if (!ass) {
+ MonoException *exc;
+
if (status == MONO_IMAGE_IMAGE_INVALID)
- mono_error_set_bad_image_name (&error, name, "");
+ exc = mono_get_exception_bad_image_format2 (NULL, fname);
else
- mono_error_set_exception_instance (&error, mono_get_exception_file_not_found2 (NULL, fname));
- goto leave;
+ exc = mono_get_exception_file_not_found2 (NULL, fname);
+ g_free (name);
+ mono_set_pending_exception (exc);
+ return NULL;
}
- if (!refOnly && prevent_running_reference_assembly (ass, &error))
- goto leave;
+ g_free (name);
result = mono_assembly_get_object_checked (domain, ass, &error);
-
-leave:
- mono_error_set_pending_exception (&error);
- g_free (name);
+ if (!result)
+ mono_error_set_pending_exception (&error);
return result;
}
return NULL;
}
- if (!refonly && prevent_running_reference_assembly (ass, &error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
-
refass = mono_assembly_get_object_checked (domain, ass, &error);
if (!refass)
mono_error_set_pending_exception (&error);
MonoAssembly *ass;
MonoAssemblyName aname;
MonoReflectionAssembly *refass = NULL;
- gchar *name = NULL;
+ gchar *name;
gboolean parsed;
g_assert (assRef);
if (mono_error_set_pending_exception (&error))
return NULL;
parsed = mono_assembly_name_parse (name, &aname);
+ g_free (name);
if (!parsed) {
/* This is a parse error... */
if (!refOnly) {
refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error);
- if (!is_ok (&error))
- goto leave;
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
}
return refass;
}
/* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */
if (!refOnly) {
refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error);
- if (!is_ok (&error))
- goto leave;
+ if (!mono_error_ok (&error)) {
+ mono_error_set_pending_exception (&error);
+ return NULL;
+ }
}
else
refass = NULL;
- if (!refass)
- goto leave;
- ass = refass->assembly;
+ if (!refass) {
+ return NULL;
+ }
}
- if (!refOnly && prevent_running_reference_assembly (ass, &error))
- goto leave;
-
- g_assert (ass);
- if (refass == NULL) {
+ if (refass == NULL)
refass = mono_assembly_get_object_checked (domain, ass, &error);
- if (!is_ok (&error))
- goto leave;
- }
- MONO_OBJECT_SETREF (refass, evidence, evidence);
-
-leave:
- g_free (name);
- mono_error_set_pending_exception (&error);
+ if (refass == NULL)
+ mono_error_set_pending_exception (&error);
+ else
+ MONO_OBJECT_SETREF (refass, evidence, evidence);
return refass;
}
aname.major, aname.minor, aname.build, aname.revision,
strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token, extra_msg);
g_free (extra_msg);
-
- } else if (!image->assembly->ref_only) {
- MonoError error;
- if (mono_assembly_get_reference_assembly_attribute (reference, &error)) {
- mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, "The following reference assembly assembly referenced from %s was not loaded. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context:\n"
- " Assembly: %s (assemblyref_index=%d)\n"
- " Version: %d.%d.%d.%d\n"
- " Public Key: %s\n",
- image->name, aname.name, index,
- aname.major, aname.minor, aname.build, aname.revision,
- strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token);
- reference = NULL; /* don't load reference assemblies for execution */
- }
- if (!is_ok (&error)) {
- reference = NULL;
- mono_error_cleanup (&error);
- }
}
mono_assemblies_lock ();
/* set the parent to something useful and safe, but mark the type as broken */
parent = mono_defaults.object_class;
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- g_assert (parent);
}
klass->parent = parent;
mono_profiler_appdomain_name (domain, domain->friendly_name);
- /* Have to do this quite late so that we at least have System.Object */
- MonoError custom_attr_error;
- if (mono_assembly_get_reference_assembly_attribute (ass, &custom_attr_error)) {
- char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
- g_print ("Could not load file or assembly %s. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context.", corlib_file);
- g_free (corlib_file);
- exit (1);
- }
- mono_error_assert_ok (&custom_attr_error);
-
return domain;
}
THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") returning %d", __func__, mono_native_thread_id_get (), ret));
mono_error_set_pending_exception (&error);
- /*
- * These need to be here. See MSDN dos on WaitForMultipleObjects.
- */
- if (ret >= WAIT_OBJECT_0 && ret <= WAIT_OBJECT_0 + numhandles - 1) {
- return map_native_wait_result_to_managed (ret - WAIT_OBJECT_0);
- }
- else if (ret >= WAIT_ABANDONED_0 && ret <= WAIT_ABANDONED_0 + numhandles - 1) {
- return map_native_wait_result_to_managed (ret - WAIT_ABANDONED_0);
- }
- else {
- /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */
- return map_native_wait_result_to_managed (ret);
- }
+
+ /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */
+ return map_native_wait_result_to_managed (ret);
}
gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(HANDLE handle, gint32 ms)
* anything up.
*/
GetCurrentProcess ();
-
- /* Check that the managed and unmanaged layout of MonoInternalThread matches */
- g_assert (MONO_STRUCT_OFFSET (MonoInternalThread, last) == mono_field_get_offset (mono_class_get_field_from_name (mono_defaults.internal_thread_class, "last")));
}
void mono_thread_cleanup (void)
MonoW32HandleNamespace sharedns;
};
-static gboolean event_handle_own (gpointer handle, MonoW32HandleType type)
+static gboolean event_handle_own (gpointer handle, MonoW32HandleType type, guint32 *statuscode)
{
MonoW32HandleEvent *event_handle;
gboolean ok;
+ *statuscode = WAIT_OBJECT_0;
+
ok = mono_w32handle_lookup (handle, type, (gpointer *)&event_handle);
if (!ok) {
g_warning ("%s: error looking up %s handle %p",
ves_icall_System_Threading_Events_SetEvent_internal (handle);
}
-static gboolean event_own (gpointer handle)
+static gboolean event_own (gpointer handle, guint32 *statuscode)
{
- return event_handle_own (handle, MONO_W32HANDLE_EVENT);
+ return event_handle_own (handle, MONO_W32HANDLE_EVENT, statuscode);
}
static void namedevent_signal (gpointer handle)
}
/* NB, always called with the shared handle lock held */
-static gboolean namedevent_own (gpointer handle)
+static gboolean namedevent_own (gpointer handle, guint32 *statuscode)
{
- return event_handle_own (handle, MONO_W32HANDLE_NAMEDEVENT);
+ return event_handle_own (handle, MONO_W32HANDLE_NAMEDEVENT, statuscode);
}
static void event_details (gpointer data)
typedef struct {
MonoNativeThreadId tid;
guint32 recursion;
+ gboolean abandoned;
} MonoW32HandleMutex;
struct MonoW32HandleNamedMutex {
};
static gboolean
-mutex_handle_own (gpointer handle, MonoW32HandleType type)
+mutex_handle_own (gpointer handle, MonoW32HandleType type, guint32 *statuscode)
{
MonoW32HandleMutex *mutex_handle;
+ *statuscode = WAIT_OBJECT_0;
+
if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
return FALSE;
mutex_handle->tid = pthread_self ();
mutex_handle->recursion++;
+ if (mutex_handle->abandoned) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: mutex handle %p was abandoned", __func__, handle);
+ mutex_handle->abandoned = FALSE;
+ *statuscode = WAIT_ABANDONED_0;
+ }
mono_w32handle_set_signal_state (handle, FALSE, FALSE);
ves_icall_System_Threading_Mutex_ReleaseMutex_internal (handle);
}
-static gboolean mutex_own (gpointer handle)
+static gboolean mutex_own (gpointer handle, guint32 *statuscode)
{
- return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX);
+ return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX, statuscode);
}
static gboolean mutex_is_owned (gpointer handle)
}
/* NB, always called with the shared handle lock held */
-static gboolean namedmutex_own (gpointer handle)
+static gboolean namedmutex_own (gpointer handle, guint32 *statuscode)
{
- return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX);
+ return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX, statuscode);
}
static gboolean namedmutex_is_owned (gpointer handle)
{
gpointer handle;
int thr_ret;
+ guint32 statuscode;
mutex_handle->tid = 0;
mutex_handle->recursion = 0;
+ mutex_handle->abandoned = FALSE;
handle = mono_w32handle_new (type, mutex_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_assert (thr_ret == 0);
if (owned)
- mutex_handle_own (handle, type);
+ mutex_handle_own (handle, type, &statuscode);
else
mono_w32handle_set_signal_state (handle, TRUE, FALSE);
tid = pthread_self ();
- if (!pthread_equal (mutex_handle->tid, tid)) {
+ if (mutex_handle->abandoned) {
+ // The Win32 ReleaseMutex() function returns TRUE for abandoned mutexes
+ ret = TRUE;
+ } else if (!pthread_equal (mutex_handle->tid, tid)) {
ret = FALSE;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)",
if (pthread_equal (mutex_handle->tid, tid)) {
mutex_handle->recursion = 0;
mutex_handle->tid = 0;
+ mutex_handle->abandoned = TRUE;
mono_w32handle_set_signal_state (handle, TRUE, FALSE);
MonoW32HandleNamespace sharedns;
};
-static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type)
+static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type, guint32 *statuscode)
{
MonoW32HandleSemaphore *sem_handle;
+ *statuscode = WAIT_OBJECT_0;
+
if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
g_warning ("%s: error looking up %s handle %p",
__func__, mono_w32handle_ops_typename (type), handle);
ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal(handle, 1, NULL);
}
-static gboolean sema_own (gpointer handle)
+static gboolean sema_own (gpointer handle, guint32 *statuscode)
{
- return sem_handle_own (handle, MONO_W32HANDLE_SEM);
+ return sem_handle_own (handle, MONO_W32HANDLE_SEM, statuscode);
}
static void namedsema_signal (gpointer handle)
}
/* NB, always called with the shared handle lock held */
-static gboolean namedsema_own (gpointer handle)
+static gboolean namedsema_own (gpointer handle, guint32 *statuscode)
{
- return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM);
+ return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM, statuscode);
}
static void sema_details (gpointer data)
return result;
}
-inline gboolean
+static inline gboolean
allocate_parameter_register_for_valuetype_win64 (ArgInfo *arg_info, ArgumentClass arg_class, guint32 arg_size, guint32 *current_int_reg, guint32 *current_float_reg)
{
return allocate_register_for_valuetype_win64 (arg_info, arg_class, arg_size, param_regs, PARAM_REGS, float_param_regs, FLOAT_PARAM_REGS, current_int_reg, current_float_reg);
}
-inline gboolean
+static inline gboolean
allocate_return_register_for_valuetype_win64 (ArgInfo *arg_info, ArgumentClass arg_class, guint32 arg_size, guint32 *current_int_reg, guint32 *current_float_reg)
{
return allocate_register_for_valuetype_win64 (arg_info, arg_class, arg_size, return_regs, RETURN_REGS, float_return_regs, FLOAT_RETURN_REGS, current_int_reg, current_float_reg);
bug-29585.cs \
priority.cs \
abort-cctor.cs \
- reference-loader.cs \
namedmutex-destroy-race.cs
if INSTALL_MOBILE_STATIC
# but that need to be compiled
PREREQ_IL_SRC=event-il.il module-cctor.il
PREREQ_CS_SRC=
-PREREQ_IL_DLL_SRC=
-PREREQ_CS_DLL_SRC=TestingReferenceAssembly.cs TestingReferenceReferenceAssembly.cs
+PREREQ_IL_DLL_SRC=event-il.il module-cctor.il
+PREREQ_CS_DLL_SRC=
-PREREQSI_IL=$(PREREQ_IL_SRC:.il=.exe) \
- $(PREREQ_IL_DLL_SRC:.il=.dll)
-PREREQSI_CS=$(PREREQ_CS_SRC:.cs=.exe) \
- $(PREREQ_CS_DLL_SRC:.cs=.dll)
+PREREQSI_IL=$(PREREQ_IL_SRC:.il=.exe)
+PREREQSI_CS=$(PREREQ_CS_SRC:.cs=.exe)
TESTSI_CS=$(TEST_CS_SRC:.cs=.exe)
TESTSI_IL=$(TEST_IL_SRC:.il=.exe)
TESTBS=$(BENCHSRC:.cs=.exe)
STRESS_TESTS=$(STRESS_TESTS_SRC:.cs=.exe)
-PREREQSI_IL_AOT=$(PREREQ_IL_SRC:.il=.exe$(PLATFORM_AOT_SUFFIX)) \
- $(PREREQ_IL_DLL_SRC:.il=.dll$(PLATFORM_AOT_SUFFIX))
-PREREQSI_CS_AOT=$(PREREQ_CS_SRC:.cs=.exe$(PLATFORM_AOT_SUFFIX)) \
- $(PREREQ_CS_DLL_SRC:.cs=.dll$(PLATFORM_AOT_SUFFIX))
+PREREQSI_IL_AOT=$(PREREQ_IL_SRC:.il=.exe$(PLATFORM_AOT_SUFFIX))
+PREREQSI_CS_AOT=$(PREREQ_CS_SRC:.cs=.exe$(PLATFORM_AOT_SUFFIX))
EXTRA_DIST=test-driver test-runner.cs $(TEST_CS_SRC_DIST) $(TEST_IL_SRC) \
$(BENCHSRC) $(STRESS_TESTS_SRC) stress-runner.pl $(PREREQ_IL_SRC) $(PREREQ_CS_SRC)
%.exe: %.cs $(TEST_DRIVER_DEPEND)
$(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll $(TEST_DRIVER_HARD_KILL_FEATURE) -out:$@ $<
-%.dll: %.cs
- $(MCS) -r:System.dll -target:library -out:$@ $<
-
-TestingReferenceReferenceAssembly.dll: TestingReferenceReferenceAssembly.cs TestingReferenceAssembly.dll
- $(MCS) -r:TestingReferenceAssembly.dll -target:library -out:$@ $<
-
%.exe$(PLATFORM_AOT_SUFFIX): %.exe
$(RUNTIME) $(AOT_BUILD_FLAGS) $<
+++ /dev/null
-using System.Runtime.CompilerServices;
-
-[assembly: ReferenceAssemblyAttribute]
-
-public class X {
- public int Y;
-}
+++ /dev/null
-// An assembly that refereces the TestingReferenceAssembly
-
-class Z : X {
- public Z () {
- Y = 1;
- }
-}
+++ /dev/null
-//
-// reference-loader.cs:
-//
-// Test for reference assembly loading
-
-using System;
-using System.IO;
-using System.Reflection;
-
-public class Tests {
- public static int Main (string[] args)
- {
- return TestDriver.RunTests (typeof (Tests), args);
- }
-
- public static int test_0_loadFrom_reference ()
- {
- // Check that loading a reference assembly by filename for execution is an error
- try {
- var a = Assembly.LoadFrom ("./TestingReferenceAssembly.dll");
- } catch (BadImageFormatException exn) {
- // Console.Error.WriteLine ("exn was {0}", exn);
- return 0;
- }
- return 1;
- }
-
- public static int test_0_load_reference ()
- {
- // Check that loading a reference assembly for execution is an error
- try {
- var an = new AssemblyName ("TestingReferenceAssembly");
- var a = Assembly.Load (an);
- } catch (BadImageFormatException exn) {
- //Console.Error.WriteLine ("exn was {0}", exn);
- return 0;
- } catch (FileNotFoundException exn) {
- Console.Error.WriteLine ("incorrect exn was {0}", exn);
- return 2;
- }
- return 1;
- }
-
- public static int test_0_reflection_load_reference ()
- {
- // Check that reflection-only loading a reference assembly is okay
- var an = new AssemblyName ("TestingReferenceAssembly");
- var a = Assembly.ReflectionOnlyLoad (an.FullName);
- var t = a.GetType ("X");
- var f = t.GetField ("Y");
- if (f.FieldType.Equals (typeof (Int32)))
- return 0;
- return 1;
- }
-
- public static int test_0_load_reference_asm_via_reference ()
- {
- // Check that loading an assembly that references a reference assembly doesn't succeed.
- var an = new AssemblyName ("TestingReferenceReferenceAssembly");
- try {
- var a = Assembly.Load (an);
- var t = a.GetType ("Z");
- } catch (FileNotFoundException){
- return 0;
- }
- return 1;
- }
-
- public static int test_0_reflection_load_reference_asm_via_reference ()
- {
- // Check that reflection-only loading an assembly that
- // references a reference assembly is okay.
- var an = new AssemblyName ("TestingReferenceReferenceAssembly");
- var a = Assembly.ReflectionOnlyLoad (an.FullName);
- var t = a.GetType ("Z");
- var f = t.GetField ("Y");
- if (f.FieldType.Equals (typeof (Int32)))
- return 0;
- return 1;
- }
-
-
- public static int test_0_load_reference_bytes ()
- {
- // Check that loading a reference assembly from a byte array for execution is an error
- byte[] bs = File.ReadAllBytes ("./TestingReferenceAssembly.dll");
- try {
- var a = Assembly.Load (bs);
- } catch (BadImageFormatException) {
- return 0;
- } catch (FileNotFoundException exn) {
- Console.Error.WriteLine ("incorrect exn was {0}", exn);
- return 2;
- }
- return 1;
- }
-
- public static int test_0_reflection_load_reference_bytes ()
- {
- // Check that loading a reference assembly from a byte
- // array for reflection only is okay.
- byte[] bs = File.ReadAllBytes ("./TestingReferenceAssembly.dll");
- var a = Assembly.ReflectionOnlyLoad (bs);
- var t = a.GetType ("X");
- var f = t.GetField ("Y");
- if (f.FieldType.Equals (typeof (Int32)))
- return 0;
- return 1;
- }
-
-}
mono_os_mutex_init_recursive (&mutex->m);
}
-static inline gint
+static inline void
mono_coop_mutex_destroy (MonoCoopMutex *mutex)
{
- return mono_os_mutex_destroy (&mutex->m);
+ mono_os_mutex_destroy (&mutex->m);
}
static inline void
mono_os_cond_init (&cond->c);
}
-static inline gint
+static inline void
mono_coop_cond_destroy (MonoCoopCond *cond)
{
- return mono_os_cond_destroy (&cond->c);
+ mono_os_cond_destroy (&cond->c);
}
static inline void
g_error ("%s: pthread_mutexattr_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
-static inline int
+static inline void
mono_os_mutex_destroy (mono_mutex_t *mutex)
{
int res;
res = pthread_mutex_destroy (mutex);
- if (G_UNLIKELY (res != 0 && res != EBUSY))
+ if (G_UNLIKELY (res != 0))
g_error ("%s: pthread_mutex_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
-
- return res != 0 ? -1 : 0;
}
static inline void
g_error ("%s: pthread_cond_init failed with \"%s\" (%d)", __func__, g_strerror (res), res);
}
-static inline int
+static inline void
mono_os_cond_destroy (mono_cond_t *cond)
{
int res;
res = pthread_cond_destroy (cond);
- if (G_UNLIKELY (res != 0 && res != EBUSY))
+ if (G_UNLIKELY (res != 0))
g_error ("%s: pthread_cond_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);
-
- return res != 0 ? -1 : 0;
}
static inline void
g_error ("%s: InitializeCriticalSectionEx failed with error %d", __func__, GetLastError ());
}
-static inline int
+static inline void
mono_os_mutex_destroy (mono_mutex_t *mutex)
{
DeleteCriticalSection (mutex);
- return 0;
}
static inline void
InitializeConditionVariable (cond);
}
-static inline int
+static inline void
mono_os_cond_destroy (mono_cond_t *cond)
{
/* Beauty of win32 API: do not destroy it */
- return 0;
}
static inline void
initialized = TRUE;
}
-static void mono_w32handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles);
-
void
mono_w32handle_cleanup (void)
{
gpointer handle = GINT_TO_POINTER (i*HANDLE_PER_SLOT+j);
for(k = handle_data->ref; k > 0; k--) {
- mono_w32handle_unref_full (handle, TRUE);
+ mono_w32handle_unref (handle);
}
}
}
handle = GUINT_TO_POINTER (i * HANDLE_PER_SLOT + k);
if (!mono_w32handle_ref_core (handle, handle_data)) {
- /* we are racing with mono_w32handle_unref_full:
+ /* we are racing with mono_w32handle_unref:
* the handle ref has been decremented, but it
* hasn't yet been destroyed. */
continue;
MonoW32HandleBase *handle_data;
if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Attempting to ref invalid private handle %p", __func__, handle);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to ref handle %p, unknown handle", __func__, handle);
return;
}
static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer);
/* The handle must not be locked on entry to this function */
-static void mono_w32handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles)
+void
+mono_w32handle_unref (gpointer handle)
{
MonoW32HandleBase *handle_data;
- gboolean destroy = FALSE, early_exit = FALSE;
- int thr_ret;
+ gboolean destroy;
if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Attempting to unref invalid private handle %p",
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to unref handle %p, unknown handle",
__func__, handle);
return;
}
destroy = mono_w32handle_unref_core (handle, handle_data, 1);
- if(destroy==TRUE) {
+ if (destroy) {
/* Need to copy the handle info, reset the slot in the
* array, and _only then_ call the close function to
* avoid race conditions (eg file descriptors being
mono_os_mutex_lock (&scan_mutex);
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Destroying handle %p", __func__, handle);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: destroy %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
- /* Destroy the mutex and cond var. We hope nobody
- * tried to grab them between the handle unlock and
- * now, but pthreads doesn't have a
- * "unlock_and_destroy" atomic function.
- */
- thr_ret = mono_os_mutex_destroy (&handle_data->signal_mutex);
- /*WARNING gross hack to make cleanup not crash when exiting without the whole runtime teardown.*/
- if (thr_ret == EBUSY && ignore_private_busy_handles) {
- early_exit = TRUE;
- } else {
- if (thr_ret != 0)
- g_error ("Error destroying handle %p mutex due to %d\n", handle, thr_ret);
-
- thr_ret = mono_os_cond_destroy (&handle_data->signal_cond);
- if (thr_ret == EBUSY && ignore_private_busy_handles)
- early_exit = TRUE;
- else if (thr_ret != 0)
- g_error ("Error destroying handle %p cond var due to %d\n", handle, thr_ret);
- }
+ mono_os_mutex_destroy (&handle_data->signal_mutex);
+ mono_os_cond_destroy (&handle_data->signal_cond);
memset (handle_data, 0, sizeof (MonoW32HandleBase));
mono_os_mutex_unlock (&scan_mutex);
- if (early_exit)
- return;
-
close_func = _wapi_handle_ops_get_close_func (type);
if (close_func != NULL) {
close_func (handle, handle_specific);
}
}
-void mono_w32handle_unref (gpointer handle)
-{
- mono_w32handle_unref_full (handle, FALSE);
-}
-
void
mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops)
{
}
}
-gboolean mono_w32handle_ops_own (gpointer handle)
+gboolean mono_w32handle_ops_own (gpointer handle, guint32 *statuscode)
{
MonoW32HandleBase *handle_data;
MonoW32HandleType type;
type = handle_data->type;
if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) {
- return(handle_ops[type]->own_handle (handle));
+ return(handle_ops[type]->own_handle (handle, statuscode));
} else {
return(FALSE);
}
}
static gboolean
-own_if_signalled (gpointer handle)
+own_if_signalled (gpointer handle, guint32 *statuscode)
{
if (!mono_w32handle_issignalled (handle))
return FALSE;
- mono_w32handle_ops_own (handle);
+ *statuscode = WAIT_OBJECT_0;
+ mono_w32handle_ops_own (handle, statuscode);
return TRUE;
}
static gboolean
-own_if_owned( gpointer handle)
+own_if_owned( gpointer handle, guint32 *statuscode)
{
if (!mono_w32handle_ops_isowned (handle))
return FALSE;
- mono_w32handle_ops_own (handle);
+ *statuscode = WAIT_OBJECT_0;
+ mono_w32handle_ops_own (handle, statuscode);
return TRUE;
}
gboolean alerted;
gint64 start;
gint thr_ret;
+ guint32 statuscode = 0;
alerted = FALSE;
case WAIT_OBJECT_0:
ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
break;
+ case WAIT_ABANDONED_0:
+ ret = MONO_W32HANDLE_WAIT_RET_ABANDONED_0;
+ break;
case WAIT_IO_COMPLETION:
ret = MONO_W32HANDLE_WAIT_RET_ALERTED;
break;
g_assert (thr_ret == 0);
if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_OWN)) {
- if (own_if_owned (handle)) {
+ if (own_if_owned (handle, &statuscode)) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned",
__func__, handle);
- ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
goto done;
}
}
for (;;) {
gint waited;
- if (own_if_signalled (handle)) {
+ if (own_if_signalled (handle, &statuscode)) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled",
__func__, handle);
- ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
goto done;
}
gint i, thr_ret;
gint64 start;
gpointer handles_sorted [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS];
+ guint32 statuscodes [MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS] = {0};
if (nhandles == 0)
return MONO_W32HANDLE_WAIT_RET_FAILED;
if (signalled) {
for (i = 0; i < nhandles; i++)
- own_if_signalled (handles [i]);
+ own_if_signalled (handles [i], &statuscodes [i]);
}
mono_w32handle_unlock_handles (handles, nhandles);
if (signalled) {
ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + lowest;
+ for (i = lowest; i < nhandles; i++) {
+ if (statuscodes [i] == WAIT_ABANDONED_0) {
+ ret = MONO_W32HANDLE_WAIT_RET_ABANDONED_0 + lowest;
+ break;
+ }
+ }
goto done;
}
gint64 start;
gboolean alerted;
gint thr_ret;
+ guint32 statuscode = 0;
alerted = FALSE;
mono_w32handle_ops_signal (signal_handle);
if (mono_w32handle_test_capabilities (wait_handle, MONO_W32HANDLE_CAP_OWN)) {
- if (own_if_owned (wait_handle)) {
+ if (own_if_owned (wait_handle, &statuscode)) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p already owned",
__func__, wait_handle);
- ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
goto done;
}
}
for (;;) {
gint waited;
- if (own_if_signalled (wait_handle)) {
+ if (own_if_signalled (wait_handle, &statuscode)) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: handle %p signalled",
__func__, wait_handle);
- ret = MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
+ ret = statuscode == WAIT_ABANDONED_0 ? MONO_W32HANDLE_WAIT_RET_ABANDONED_0 : MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
goto done;
}
/* Called by WaitForSingleObject and WaitForMultipleObjects,
* with the handle locked (shared handles aren't locked.)
* Returns TRUE if ownership was established, false otherwise.
+ * If TRUE, *statuscode contains a status code such as
+ * WAIT_OBJECT_0 or WAIT_ABANDONED_0.
*/
- gboolean (*own_handle)(gpointer handle);
+ gboolean (*own_handle)(gpointer handle, guint32 *statuscode);
/* Called by WaitForSingleObject and WaitForMultipleObjects, if the
* handle in question is "ownable" (ie mutexes), to see if the current
mono_w32handle_ops_signal (gpointer handle);
gboolean
-mono_w32handle_ops_own (gpointer handle);
+mono_w32handle_ops_own (gpointer handle, guint32 *statuscode);
gboolean
mono_w32handle_ops_isowned (gpointer handle);
mono_w32handle_unlock_handle (gpointer handle);
typedef enum {
- MONO_W32HANDLE_WAIT_RET_SUCCESS_0 = 0,
- MONO_W32HANDLE_WAIT_RET_ALERTED = -1,
- MONO_W32HANDLE_WAIT_RET_TIMEOUT = -2,
- MONO_W32HANDLE_WAIT_RET_FAILED = -3,
+ MONO_W32HANDLE_WAIT_RET_SUCCESS_0 = 0,
+ MONO_W32HANDLE_WAIT_RET_ABANDONED_0 = MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS,
+ MONO_W32HANDLE_WAIT_RET_ALERTED = -1,
+ MONO_W32HANDLE_WAIT_RET_TIMEOUT = -2,
+ MONO_W32HANDLE_WAIT_RET_FAILED = -3,
} MonoW32HandleWaitRet;
MonoW32HandleWaitRet