none
.NET Programm läuft auf x64 Maschinen in Endlosschleife - x64 optimizer Bug? RRS feed

  • Frage

  • Hallo,

    Das folgende Console-Program läuft als Release und AnyCPU kompiliert unter x64 in einer Endlosschleife wenn man es ohne Debugger startet. Mit Debugger oder auf x86 läuft es einwandfrei. Es scheint als ob der Runtime-Optimizer von x64 einen Bug hat. Das Probem ist mit .NET 2.0 und .NET 4.0 nachstellbar.

    Program flow:

    ·         locale variable switchNextUrl in Test() will be initialized with false

    ·         before calling the function Login(), the variable will be set to true (will be written in the console output)

    ·         the function Login throws a socket exception

    ·         after executing the exception handler for SocketException, the variable is false! The only place where the code set the variable back to false is the BusyException handle, which will not be executed!

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Net.Sockets;

    using System.Net;

    using System.Threading;

     

    namespace TestLoop

    {

        class Program

        {

            static void Main(string[] args)

            {

                try

                {

                    new Program().Test();

                }

                catch (Exception e)

                {

                    Console.WriteLine("Function fails: {0}", e);

                }

                Console.WriteLine("Finished");

                Console.WriteLine("Press enter to exit");

                Console.ReadLine();

     

            }

     

     

            void Test()

            {

                try

                {

                    Console.WriteLine("(c) Michael Geramb");

                    bool switchNextUrl = false;

                    // Loop through all urls, if one fails

                    int urlIndex = 1;

                    while (urlIndex <= 2)

                    {

                        Console.WriteLine("Try index {0}", urlIndex);

                        try

                        {

                            switchNextUrl = true;

                            Console.WriteLine("switchNextUrl={0} (before Login)", switchNextUrl);

                            Login(); // throws socket exception

                            return;

                        }

                        catch (SocketException exception)

                        {

                            Console.WriteLine("SocketException: {0}", exception.Message);

                        }

                        catch (BusyException exception)

                        {

                            Console.WriteLine("OpwsException {0}", exception.Message);

                            Console.WriteLine("set switchNextUrl to false");

                            switchNextUrl = false; // Try again same url

     

                        }

                        Console.WriteLine("switchNextUrl={0} (before check)", switchNextUrl);

                        if (switchNextUrl)

                        {

                            urlIndex++;

                        }

     

                    }

                    throw new Exception("Error");

     

                }

                catch (Exception e)

                {

                    Console.WriteLine("Execute fails: {0}", e);

                    throw;

                }

            }

     

            void Login()

            {

                Thread.Sleep(500);

                throw new SocketException((int)SocketError.HostNotFound);

            }

     

            class BusyException : Exception

            {

            }

        }

     

    }

    Grüße,

    michi!

    Donnerstag, 28. Oktober 2010 13:49

Antworten

  • Hallo,

    danke Euch allen. Wie oben beits von Marcel beschrieben habe ich den Bug hier https://connect.microsoft.com/VisualStudio/feedback/details/618529/net-2-0-net-4-0-jiter-x64-bug gemeldet. Bin leider erst jetzt dazugekommen das zu bearbeiten, eigentlich ist in Österreich heute Feiertag und deshalb bin ich nicht bei der Arbeit.

    Für meinen eigenene Code habe ich bereits Freitag einen Workaround eingebaut, und für das Flag eine Membervariable der Klasse verwendet, dann gibt es keine Probleme. Da die Stelle mit einem Lock ohnedies vor Multithreading geschützt ist, ist das akzeptal und funktioniert gut.

    Grüße,
       michi!

    Montag, 1. November 2010 18:16
  • Hallo Michael,

    schön, dass Du meinen Rat befolgt hast, bei Connect einen Report diesbezüglich zu machen.
    Ich habe dort gerade noch kurz einen (es gibt ja viele) Workaround (nur der Vollständigkeit halber) gepostet:

    • Of course you can always put an: [MethodImpl(MethodImplOptions.NoOptimization)]
      over the
      method you do not want to be optimized. This way your code will behave the intended way you think of it.

      [MethodImplOptions Enumeration (System.Runtime.CompilerServices)]
      http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx

      [MethodImplAttribute Class (System.Runtime.CompilerServices)]
      http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimplattribute.aspx


    trotzdem nochmals: Der JIT-ter kann durchaus Methoden zusammenfassen, in-linen oder tail-recursion umformen etc..
    Es sollte durch meinen Artikel-Link auch klar geworden sein, dass ein Debug-Verhalten by design anders sein kann, als ein Release.
    Speziell in throw-Szenarien, wie Scotts Beispiel auch zeigt. Das (Scotts Beispiel) ist kein "Bug" und kein "wrong JIT code".


    ciao Frank
    Montag, 1. November 2010 19:40
  • Hallo,

     

    Microsoft stuft diesen Bug als offenbar nicht wichtig ein. Hier die Antwort auf meinen Support-Request:

    Guten Morgen Herr Geramb,

     

    Der zuständige „Principal Development Lead“ (Kevin Frei) hat für die aktuellen .NET Versionen 2/4 einen Fix abgelehnt.

    Er verspricht allerdings, diesen Bug in der nächsten .NET Version (nicht in einem SP!!, sondern in .NET 5, oder wie auch immer diese Version heißen wird) zu beheben.

     

    Er schlägt vor die Optimierung für Main abzuschalten…

     

    Put this:
    
    
    [System.Runtime.CompilerServices.MethodImpl
    (System.Runtime.CompilerServices.MethodImplOptions
    .NoOptimization)]
    
    
     
    
    
    right before the Main() method body to work around this particular problem.
    
    
    I don't think we should need to QFE the issue, given that it's got an easy work around.
    
    
    I'm happy to hear the customer's argument, but a QFE is not likely to make the customer happy, since they would need to install
    
    
    the QFE on any machines this application were going to run on.
    
    
    I'll make sure we get the bug fixed in the next release of the framework.
    
    
     
    
    
    -Kev
    
    

     

    …um das Fehlverhalten zu umgehen.

     

    Unabhängig davon würde ein Fix auch weitere Umstände mit sich bringen, da Sie diesen immer mitverteilen müssten, was Sie standardmäßig nicht dürften.

    Dazu müssten wir wiederum eine Distribution-Lizenz beantragen, um dies z.B. mit in Ihrem Setup verteilen zu dürfen.

    Ansonsten muss jeder Ihrer Kunden bei MS den Fix selbst über einen Service Request „abholen“.

     

    Leider kann ich keine bessere Aussage anbieten.

     

    Klärt dies die Sachlage, um die Anfrage abzuschließen?

     

    Da es sich um einen Bug handelt ist die Anfrage selbstverständlich ohne Abzug einer Ihrer MSDN-Anfragen.

     

     

    Montag, 8. November 2010 08:31

Alle Antworten

  • Hallo Michael

    kann ich bestätigen, scheint mir auf den ersten Blick auch ein Bug.  Suche noch Details...
    Donnerstag, 28. Oktober 2010 14:04
  • Hallo Zusammen,

     

    ja, ich kann es auch bestätigen. Wenn man urlIndex als long deklariert funktioniert das Programm korrekt.

     

    Gruß,

    Sergej.

    Donnerstag, 28. Oktober 2010 14:31
  • Es funktioniert übrigens auch dann korrekt, wenn man im SocketException Handler lesend auf switchToNextUrl zugreift (Z.B. Console.WriteLine(switchToNextUrl );)

    Donnerstag, 28. Oktober 2010 14:34
  • korrekt, wenn man im SocketException Handler lesend auf switchToNextUrl zugreift

    ja,
    soweit ich den native x64 Assembler-Code des JITers
    überblicke, wird andernfalls insbesondere die Codezeile:
      switchNextUrl = true;
    falsch umgesetzt (!?),
    mir scheint es wird da nur ein temporärer Merker (für nachfolgendes WriteLine) auf true gesetzt, nicht die effektive 'switchNextUrl' Variable.
    Und schockierenderweise mit jedem zusätzlichem WriteLine ein Merker (technisch: rbp+offset) zusätzlich!?

    Ich schätze du solltest bei MS ein 'Garantiefall' anmelden
       (IMHO sind solche Fehler im JITer gravierend, das darf bei derart simplen Code nicht vorkommen).

    PS
    der MSIL-Code (auch im ReleaseBuild) scheint mir noch korrekt.

    Donnerstag, 28. Oktober 2010 17:14
  • Hallo Michael,

    ich will auch nur kurz das Verhalten bestätigen. Man muss natürlich das Release direkt aus dem x64 Ordner oder über [Strg-F5] starten. Ein Senieren über den Assembler ist hier IMHO wenig sinnreich.
    Bitte melde das möglichst reproduzierbar geschilderte Verhalten hier:

    [Visual Studio and .NET Framework | Microsoft Connect]
    https://connect.microsoft.com/VisualStudio

    hier haben wir MVPs (auch andere) insbesondere auch die Möglichkeit die Prio zu pushen, wenn Dir oder anderen das ein wichtiger Unternehmens-kritischer Punkt ist, um so ggf. einen Hotfix zu erwirken. Einige gibt es ja bereits schon, etwa den QFE 2280741 im C++ Compiler. Am besten hier auch den Link zu Deinem Bug-Report posten.

    ______________

    zu beachten und sicher hilfreich (zunächst mal als Referenz) hier auch:

    [Scott Hanselman - Release IS NOT Debug: 64bit Optimizations and C# Method Inlining in Release Build Call Stacks]
    http://www.hanselman.com/blog/ReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx

    [Erstellen und Auslösen von Ausnahmen (C#-Programmierhandbuch)]
    http://msdn.microsoft.com/de-de/library/ms173163.aspx


    ciao Frank
    Samstag, 30. Oktober 2010 09:43
  • Michael,
    zur Sicherheit damit keine Verwirrung aufkommt:
    du hast schon richtig erkannt dass das Problem in der .NET Runtime liegt.
    Und es ist da nahezu absolut ausgeschlossen, dass der Bug vom "C++ Compiler" kommt (wie anderswo wenig sinnreich erwähnt), bzw mit dessen QFE-Fix mal behoben weden könnte.

    [100% EOT, ausser es gäbe doch noch Fix via C++ Compiler anstelle im vom JITer erstellten Code]

    Sonntag, 31. Oktober 2010 10:27
  • Thomas,

    Nur damit keine Verwirrung entsteht ;-) es sagt keiner, dass dieses Problem im "C++ Compiler" ursächlich sein muß, das hast Du wohl mißverstanden (wir sind hier in der "C#" Gruppe).
    Es wurde nur gesagt (von mir), dass es im Bereich Optimizing C++ x64 bereits Fixes gegeben hat. Für mich liegt da die Folge nahe, dass auch Fehler im Bereich C# / JIT / x64 enthalten sein können. 


           Thomas schrieb:  >  "(wie anderswo wenig sinnreich erwähnt)", 

    scheinbar hatte sich der Sinn bei Dir durch das Mißverständnis nicht erschlossen.



           Frank schrieb: > Ein Senieren über den Assembler ist hier IMHO wenig sinnreich 

    um meine Formulierung da etwas zu begründen ... ich denke, das Senieren über Assembler sollte man in diesem Fall (und dieser C# Gruppe) eher Microsoft überlassen, und deren Experten begründen lassen durch meinen Vorschlag von einem Request bei https://connect.microsoft.com/VisualStudio, da dies ja nun auch andere angeht und ich und andere da sicher letztlich auch abgesicherte 100%ige Erkenntnisse / Lösungen und ggf. QFE's haben wollen, wenn sich dies denn letztlich als Bug herausstellt. Wenn Du das trotzdem hier machen willst, habe ich da nichts dagegen - ich finde es halt nur besser an anderer Stelle, aber no prob. 


    ciao Frank
    Sonntag, 31. Oktober 2010 12:44
  •    (IMHO sind solche Fehler im JITer gravierend, das darf bei derart simplen Code nicht vorkommen).

    leider scheint hierzu bei einigen offensichtliche Unkenntnis oder Vertuschungsgefahr über Fehler im JITer zu herrschen, daher ist es jetzt halt _meine_ Pflicht die Fakten klarzulegen:

    es besteht bei Bugs im JITer
       (oder VM, insbeso bei direkt im Internet exponierten Apps wie zB Silverlight/ASP.NET/Azure)
    unmittelbar ein gewisses Potential/Risiko eines Zero-day-attack!
    Solange hier nicht bewiesen ist, dass es etwa 'bloss' ein Fehlverhalten zB in der flow/scope-Analyse/Logik des JITers ist, können wesentlich fatalere Nebeneffekte durch Code-Defekte
      (ala buffer-overflow, stack-corruption uva)
    _nicht_ ausgeschlossen werden.

    Weil Michael das Problem bereits hier _veröffentlicht_ hat, könnten darauf spezialisierte Hacker jetzt sehr schnell allfällige daraus folgende Nebeneffekte ausnützen!

    Daher ist eine sofortige Analyse auch des generierten Codes äusserst sinnvoll und geboten, auch hier in Foren.
    IMHO ist ein Bug-Report an MS-Connect hier evtl gar zu wenig/langsam,
    einiges spricht sogar für Security-Report:
    http://www.microsoft.com/security/msrc/report.aspx

    wo es ja vor wenigen Wochen einen viel naheliegenderen Fall gab
    http://www.microsoft.com/technet/security/Bulletin/MS10-077.mspx

     "This security update is rated Critical for Microsoft .NET Framework 4.0 on supported x64-based ...
    The security update addresses the vulnerability by modifying the way that
    the JIT compiler optimizes code."

     (ich hoffe jetzt bloss, MS10-077 hat uns den Bug nicht erst recht eingebracht!)
    Sonntag, 31. Oktober 2010 13:36
  • Thomas,

        > IMHO ist ein Bug-Report an MS-Connect hier evtl gar zu wenig

    wie gesagt, meine Ansicht: am besten Bugreport bei Connect (wie ich vorschlug). Wir "erreichen" Microsoft hier erfahrungsgemäß am schnellsten (zum Teil Tage - wie gesagt durch Ratings von MVPs durchaus z.T. schneller). Zumal die es dann eh an das Team dort weiterleiten müssten und es dann unnötige Verzögerungen gäbe. 



        > ich hoffe jetzt bloss, [...] den Bug [...]

    ich persönlich bestätige nur das "Verhalten", nicht, dass es ein "Bug" ist.  
    "Vermutungen" wie "hoffen" sind da IMHO eher nicht förderlich, wenn noch nicht mal die Sachlage von Microsoft verifiziert ist. Das sollte erst dann geschehen. Es wäre ein Fehler zu denken - es geht nicht so wie ich es denke, also ist Microsoft Schuld. In einem hohen Prozentsatz ergibt sich die Erklärung durch die Experten dort.


    ciao Frank
    Sonntag, 31. Oktober 2010 14:15
  • Hallo,

    ich wollte eigentlich einen Support Call dafür aufmachen (Ist nur nicht ganz so einfach, zuerst muss man sich durch die Web-Site handeln, dort steht dann eine Telefonnummer bei der man sich mit der MSDN-ID einen Support Vertrag holen muss, wenn man dann anruft hängt man ewig in der Warteschleife um dann eine neue URL zu bekommen, von der muss man dann noch ein Formular laden und zurüsckschicken und auf die Support Vertrag ID warten - Ist sich Freitag nicht mehr ausgegangen)

    Soll ich das Problem also besser gleich an einer von Euch vorgeschlagen URL melden? Da das Problem bei .NET 2.0 und 4.0 auftritt scheint es wohl schon älter zu sein.

    Den Code habe ich nochmal vereinfacht:

    using System;
    using System.Net.Sockets;
    using System.Net;
    
    namespace Test
    {
      class Program
      {
        static void Main(string[] args)
        {
          Console.WriteLine("(c) Michael Geramb, AutomationX, michael.geramb@automationx.com");
          Console.WriteLine("Platform: {0}", IntPtr.Size * 8);
          bool flag = false;
          try
          {
            flag = true;
            Console.WriteLine("flag={0} (should be True)", flag);
            ThrowSocketException(); // throws socket exception
            return;
          }
          catch (SocketException)
          {
            Console.WriteLine(" -> SocketException handler");
          }
          catch (Exception)
          {
            Console.WriteLine("We never reach this line");
            flag = false;
          }
          Console.WriteLine("flag={0} (should be True)", flag);
          if (flag)
            Console.WriteLine("program works correct");
          else
            Console.WriteLine("-> flag has a wrong value -> this is a bug!");
    
          Console.ReadLine();
        }
    
        static void ThrowSocketException()
        {
          throw new SocketException((int)SocketError.HostNotFound);
        }
      }
      
    }
    

    Grüße,

    michi!

     

    Montag, 1. November 2010 12:22
  • Hallo Michael,

    ja, melde das Problem wie gesagt in dem Link, den ich Dir schrieb (Microsoft Connect Visual Studio), (wo Du nicht drauf geantwortet hast). Und lies Dir ggf. nochmal die (dort auch verlinkten) Hinweise von Scott Hanselman's Hinweise zu optimierten x64 Methoden und throw etc.. 


    ciao Frank
    Montag, 1. November 2010 12:50
  • Hallo zusammen,

    Habe dieses Verhalten eskaliert in zwei von unserer Internen Tools. Falls ich Neuigkeiten bekomme melde ich sie hier im Forum.

    @Michi: Konnte auch dieses Verhalten nachvollziehen (x64 und .NET 4). Etwas ähnliches (weil man das Threading verwendet hat, kann aber ein Neuer Issue sein) ist das KB 2077754: http://support.microsoft.com/kb/2077754

    Wie sieht das bei euch aus?  à clrjit.dll | 4.0.30319.202 | 1,524,552 | 15-Jul-2010 | 21:00 |

    Vielen Dank an alle für Eure Unterstützung.

    Grüße,

    Robert

    Montag, 1. November 2010 13:00
    Moderator
  • Wie sieht das bei euch aus?  à clrjit.dll | 4.0.30319.202 | 1,524,552 | 15-Jul-2010 | 21:00

    Hallo Robert,
    ja, ich habe auch diese Version aus dem von mir genannten MS10-077 Hotfix, KB 2160841:
    http://support.microsoft.com/kb/2160841

    dort der x64 GDR-Branch.

    Montag, 1. November 2010 13:09
  • Hallo Michi,

    Es scheint ein Optimization Bug zu sein. Was Du noch machen kannst…so wie schon oft hier gesagt wurde:

    1)    Ein Bug auf Connect aufmachen …sollst und den Link sagen das wir dort wählen können.

    2)    Einen Support Call dafür aufmachen…hast schon versucht…versuch noch mal den Support Call…ich glaube das als MSDN Subscriber hat man 5 kostenloses Meldungen beim Support.

    Habe dieses Verhalten eskaliert in zwei von unserer Internen Tools, andere als Connect und Support Call.

    PS: Bei deinem vereinfachten Code als Workaround (Referenz zu flag in dem catch block...dann geht es):

    ·         using System;

    ·         using System.Net.Sockets;

    ·         using System.Net;

    ·          

    ·         namespace Test

    ·         {

    ·           class Program

    ·           {

    ·             static void Main(string[] args)

    ·             {

    ·               Console.WriteLine("(c) Michael Geramb, AutomationX, michael.geramb@automationx.com");

    ·               Console.WriteLine("Platform: {0}", IntPtr.Size * 8);

    ·               bool flag = false;

    ·               try

    ·               {

    ·                 flag = true;

    ·                 Console.WriteLine("flag={0} (should be True)", flag);

    ·                 ThrowSocketException(); // throws socket exception

    ·                 return;

    ·               }

    ·               catch (SocketException)

    ·               {

    ·                 Console.WriteLine(" -> SocketException handler");

      //do something with flag here.

      Console.WriteLine("flag={0} (should be True)", flag);

    ·               }

    ·               catch (Exception)

    ·               {

    ·                 Console.WriteLine("We never reach this line");

    ·                 flag = false;

    ·               }

    ·               Console.WriteLine("flag={0} (should be True)", flag);

    ·               if (flag)

    ·                 Console.WriteLine("program works correct");

    ·               else

    ·                 Console.WriteLine("-> flag has a wrong value -> this is a bug!");

    ·          

    ·               Console.ReadLine();

    ·             }

    ·          

    ·             static void ThrowSocketException()

    ·             {

    ·               throw new SocketException((int)SocketError.HostNotFound);

    ·             }

    ·           }

    ·           

    ·         }

     

    Grüße,

    Robert

    Montag, 1. November 2010 13:54
    Moderator
  • Hallo,

    Michael hat mittlerweile ein Feedback auf connect.microsoft.com eingetragen. Ihr könnt dort eure Workarounds und/oder Kommentare hinzufügen bzw. für die Wichtigkeit des Feedbacks voten:

    https://connect.microsoft.com/VisualStudio/feedback/details/618529/net-2-0-net-4-0-jiter-x64-bug

    Gruß
    Marcel

    Montag, 1. November 2010 15:05
    Moderator
  • Hallo,

    danke Euch allen. Wie oben beits von Marcel beschrieben habe ich den Bug hier https://connect.microsoft.com/VisualStudio/feedback/details/618529/net-2-0-net-4-0-jiter-x64-bug gemeldet. Bin leider erst jetzt dazugekommen das zu bearbeiten, eigentlich ist in Österreich heute Feiertag und deshalb bin ich nicht bei der Arbeit.

    Für meinen eigenene Code habe ich bereits Freitag einen Workaround eingebaut, und für das Flag eine Membervariable der Klasse verwendet, dann gibt es keine Probleme. Da die Stelle mit einem Lock ohnedies vor Multithreading geschützt ist, ist das akzeptal und funktioniert gut.

    Grüße,
       michi!

    Montag, 1. November 2010 18:16
  • Hallo Michael,

    schön, dass Du meinen Rat befolgt hast, bei Connect einen Report diesbezüglich zu machen.
    Ich habe dort gerade noch kurz einen (es gibt ja viele) Workaround (nur der Vollständigkeit halber) gepostet:

    • Of course you can always put an: [MethodImpl(MethodImplOptions.NoOptimization)]
      over the
      method you do not want to be optimized. This way your code will behave the intended way you think of it.

      [MethodImplOptions Enumeration (System.Runtime.CompilerServices)]
      http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx

      [MethodImplAttribute Class (System.Runtime.CompilerServices)]
      http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimplattribute.aspx


    trotzdem nochmals: Der JIT-ter kann durchaus Methoden zusammenfassen, in-linen oder tail-recursion umformen etc..
    Es sollte durch meinen Artikel-Link auch klar geworden sein, dass ein Debug-Verhalten by design anders sein kann, als ein Release.
    Speziell in throw-Szenarien, wie Scotts Beispiel auch zeigt. Das (Scotts Beispiel) ist kein "Bug" und kein "wrong JIT code".


    ciao Frank
    Montag, 1. November 2010 19:40
  • Hallo an alle

    Irrtum vorbehalt  (hier: Win7, 4.0 x64-ReleaseBuild), aber ich habe hier eine 'verbesserte' Variante,
    welche IMHO zeigt dass
    1) es zB keine Inlining-Optimierung sein kann
    2) Unter 'Vorbelastung' (hier per GC forciert) fatalerweise zufällige Werte produziert  (wegen uninitialisertem Stack-Speicher für 'number'!)

    class Program
    {
    	static void Main(string[] args)
    	{
    		System.Threading.Thread.Sleep(200);
    		GC.Collect();
    		GC.WaitForPendingFinalizers();
    		System.Threading.Thread.Sleep(200);
    		GC.Collect();
    		GC.WaitForPendingFinalizers();
    
    		Test();
    	}
    
    	static void Test()
    	{
    		int number = 99;
    
    		try
    		{
    			number = 11;
    
    			if (Environment.TickCount != -1)
    				throw new ApplicationException();
    
    			return;
    		}
    		catch (ApplicationException)
    		{
    			Console.WriteLine("-> ApplicationException handler");
    		}
    		catch
    		{
    			number = 77;
    		}
    
    		if (number == 11)
    			Console.WriteLine("program works correct (number=11).");
    		else
    			Console.WriteLine("-> number has a wrong value of {0} -> this is a bug!", number );
    
    		Console.ReadKey(true);
    	}
    }
    
    
    Dienstag, 2. November 2010 01:00
  • Hallo Thomas,

         > es zB keine Inlining-Optimierung sein kann ...

    das hatte ich schon geprüft, sonst hätte ich es gesagt, dass es eine solche ist.
    Leichter kann man das ggf. prüfen, indem man:

      [MethodImpl(MethodImplOptions.NoInlining)]

    vor die Methode schreibt. Das Verhalten zeigt sich dann ebenfalls, deswegen ist der Grund keine Inlining-Optimierung.

    kurz zu ApplicationException noch angemerkt:

    • ... It was originally thought that custom exceptions should derive from the ApplicationException class; however in practice this has not been found to add significant value. For more information, see Best Practices for Handling Exceptions 


    ciao Frank
    Dienstag, 2. November 2010 06:29
  • Hallo,

     

    Microsoft stuft diesen Bug als offenbar nicht wichtig ein. Hier die Antwort auf meinen Support-Request:

    Guten Morgen Herr Geramb,

     

    Der zuständige „Principal Development Lead“ (Kevin Frei) hat für die aktuellen .NET Versionen 2/4 einen Fix abgelehnt.

    Er verspricht allerdings, diesen Bug in der nächsten .NET Version (nicht in einem SP!!, sondern in .NET 5, oder wie auch immer diese Version heißen wird) zu beheben.

     

    Er schlägt vor die Optimierung für Main abzuschalten…

     

    Put this:
    
    
    [System.Runtime.CompilerServices.MethodImpl
    (System.Runtime.CompilerServices.MethodImplOptions
    .NoOptimization)]
    
    
     
    
    
    right before the Main() method body to work around this particular problem.
    
    
    I don't think we should need to QFE the issue, given that it's got an easy work around.
    
    
    I'm happy to hear the customer's argument, but a QFE is not likely to make the customer happy, since they would need to install
    
    
    the QFE on any machines this application were going to run on.
    
    
    I'll make sure we get the bug fixed in the next release of the framework.
    
    
     
    
    
    -Kev
    
    

     

    …um das Fehlverhalten zu umgehen.

     

    Unabhängig davon würde ein Fix auch weitere Umstände mit sich bringen, da Sie diesen immer mitverteilen müssten, was Sie standardmäßig nicht dürften.

    Dazu müssten wir wiederum eine Distribution-Lizenz beantragen, um dies z.B. mit in Ihrem Setup verteilen zu dürfen.

    Ansonsten muss jeder Ihrer Kunden bei MS den Fix selbst über einen Service Request „abholen“.

     

    Leider kann ich keine bessere Aussage anbieten.

     

    Klärt dies die Sachlage, um die Anfrage abzuschließen?

     

    Da es sich um einen Bug handelt ist die Anfrage selbstverständlich ohne Abzug einer Ihrer MSDN-Anfragen.

     

     

    Montag, 8. November 2010 08:31
  • Hallo Michael,

    Microsoft stuft diesen Bug als offenbar nicht wichtig ein.

    Der Microsoft Development Lead hat schnell reagiert und das von Dir beschriebene Fehlverhalten als aktiven Bug anerkannt, das im nächsten Frameworkrelease verbessert werden soll. Das ist ja schon mal allerhand. Du hast etwas gefunden, was durch alle bisherigen Qualitätskontrollen durchgeschlüpft ist (und hast die Ursache richtig erkannt: ein Optimizer-Bug). Und dank Deines Einsatzes kann nun die ganze .NET-Developer-Community (weltweit) auf ein einfaches Workaround zurückgreifen. Ist das nichts? - Offenbar wird der Bug zum aktuellen Zeitpunkt nicht als Sicherheitsrisiko eingestuft. Das kann sich aber blitzartig ändern, wenn entsprechende Gefährdungspotentiale gefunden/gemeldet werden.

    Gruß
    Marcel

     

    Montag, 8. November 2010 08:59
    Moderator
  • Hallo Michael,

    OK, einerseits ist es als Bug anerkannt  (NB: wie ich ja sofort erkannt), aber andererseits
    bin ich sprachlos, Microsoft will offenbar erst einen Zero-day Attack abwarten.
    Ich bin immer noch sicher dass es plötzlich doch einen Security-Hotfix geben wird, der das Problem  (verdacht: heimlich) fixen wird.

    Was Microsoft hier übrigens völlig vergisst, dass es nicht so sehr um neu geschriebenen Code geht (Workaround mit Attribut noch möglich),
    sondern potentiell um Milliarden von Zeilen Code weltweit, welche schon geschrieben sind  (jetzt ggf erstmals unter x64 laufen), inklusive Code von Microsoft selber, auch in Framework-Runtime Assemblies selber (VM-Hacks!).

    Und der Bug tritt ja auch bei zu trivialem Code auf, die Chance dass es mal irgendwo eine sicherheitsrelevante API betrifft ist sehr hoch.
    Microsoft sollte IMHO allermindestens einen KB-Artikel aufschalten, der die Entwickler auf den Attribut-Workaround aufmerksam macht.

    Naja, aber es passt alles ins Bild von Microsoft in den letzten 2-3 Jahren, aber mehr als mehrfache Reports kann man halt als Entwickler nicht machen.
    Aber falls der Bug heimlich gefixt wird, könnte dies ein Fall für Anwälte (in den USA) werden.
    Auch mal abwarten, auf welche Ideen die Hacker da so kommen.

    Michael, Danke für deine Mitteilung hier in den Foren.
    Vielleicht wird dies später ja mal auch lehrreich für Microsoft selber?

    Montag, 8. November 2010 09:00
  • Hallo Michael,

    danke für Deine Rückmeldung und somit die wertvolle Information für diese Gruppe. Gut, dass Du meine Vorschlag mit dem Connect-Report aufgenommen hast. 

    Damit schlägt Microsoft genau den Workaround vor, den ich im Connect-Artikel gepostet habe. Insofern "könnte" man - um die Übersicht für spätere User zu verbessern - mein Posting mit dem Vorschlag (mit dem NoOptimization) / und Deins als (vorläufige) Antwort markieren.



              > Klärt dies die Sachlage, um die Anfrage abzuschließen?

    ja, für mein Dafürhalten können wir den Punkt hier abschließen.
    Freut mich, dass das jetzt geklärt wurde, wenngleich es auch erst später gefixt wird.


    ciao Frank
    Montag, 8. November 2010 09:24
  • Hallo Thomas,

    Und der Bug tritt ja auch bei zu trivialem Code auf, die Chance dass es mal irgendwo eine sicherheitsrelevante API betrifft ist sehr hoch.

    Ich teile Deine Sorge, habe aber z.Z. keine konkreten Anhaltspunkte für ein aktuelles Gefährdungsszenario. Wenn Du da andere Einsichten hast, würde ich Dich bitten, mir diese offline, unter marcel.roma(bei)acm.org mitzuteilen.

    Gruß
    Marcel

    Montag, 8. November 2010 09:48
    Moderator
  • aber z.Z. keine konkreten Anhaltspunkte für ein aktuelles Gefährdungsszenario (außer DOS). Wenn Du da andere Einsichten hast, würde ich Dich bitten, mir diese offline, unter marcel.roma(bei)acm.org mitzuteilen.
    Hallo Marcel,
    eher wäre es nützlich zu wissen, ob du (bzw andere) meine 'verbesserte' Variante des Bugs
      (hier gepostet, oder beim Connect-Eintrag als Attach: x64_JIT_Bug_Uninit.zip)
    mal angesehen hast, und welche Zahlenwerte (über viele Starts) du bekommst.
    Falls du auch 'zufällige' Werte bekommst, dann wird nämlich auf uninitialisierten Stack zugegriffen, was bei einem managed JITer schlicht inakzeptabel ist.

    Privat-EMails sehe ich hier als wenig sinnvoll (bis riskant), da Thema längst 'öffentlich' ist, und ich dich persönlich wie deine Absichten ja nicht kenne.
    Montag, 8. November 2010 10:05
  • Hallo Thomas, 

    danke für Deine Antwort.

    wäre es nützlich zu wissen, ob du (bzw andere) meine 'verbesserte' Variante des Bugs
      (hier gepostet, oder beim Connect-Eintrag als Attach: x64_JIT_Bug_Uninit.zip)
    mal angesehen hast, und welche Zahlenwerte (über viele Starts) du bekommst.

    Ich hatte Dein Code getestet (VS 2008, Release Build, Any CPU, AMD Athlon 64 X2, .NET 3.5). Ich erhielt dabei nur den Zahlenwert 99 bei 100 sukzessiven Ausführungen.

    Anschließend habe ich testhalber im try/catch-Block noch das eingefügt:

    finally {
      Console.WriteLine("number={0}", number);
    }
    

    Der Code wurde nun erfolgreich ausgeführt (number==11).

    Privat-E-Mails sehe ich hier als wenig sinnvoll (bis riskant), da Thema längst 'öffentlich' ist [...]

    Ich respektiere Deine Option und habe Verständnis dafür. Ich würde Dich aber trotzdem bitten, wenn Du konkrete Gefährdungsszenarien hast, diese an Microsoft weiterzuleiten und nicht online zu stellen. Auf connect.microsoft.com gibt es z.Z. noch keine Stellungsnahme zum aktiven Bug.

    Gruß
    Marcel

    Montag, 8. November 2010 11:31
    Moderator
  • VS 2008, Release Build, Any CPU, AMD Athlon 64 X2, .NET 3.5). Ich erhielt dabei nur den Zahlenwert 99 bei 100 sukzessiven Ausführungen.
    Marcel,
    dann ist diese Variante uU sogar Versions/CPU abhängig,
    hier: VS2010: .NET4+x64; Win7, intel QuadCore Q6600. 

    Nachtrag, Zielframework auf 3.5 gestellt, dann gibt es auch hier 99.
    Es scheint mit diesem Code also primär ein 4.0-Bug.
    Montag, 8. November 2010 11:43