This is the mail archive of the cygwin mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: 1.7.10/1.7.11: .Net programs started from a cygwin console may fail.

I have also noticed this issue; again it was with the XML serialization functions like Andres Martinelli originally noted.  The root of the problem is that Windows environment variables are not case sensitive, while they *are* in a Unix environment.  Cygwin passes an environment block with duplicate identically-named variables (if case insensitive; unique if case sensitive), and this will make some Windows programs go boom, because they assume the block is maintained in a case-insensitive manner.

Here's a full stack trace:

Unhandled Exception: System.ArgumentException: Item has already been added. Key in dictionary: 'tmp'  Key being added: 'tmp'
   at System.Collections.Specialized.StringDictionary.Add(String key, String value)
   at System.CodeDom.Compiler.Executor.ExecWaitWithCaptureUnimpersonated(SafeUserTokenHandle userToken, String cmd, String currentDir, TempFileCollection tempFiles, String& outputName, String& errorName, String trueCmdLine)
   at Microsoft.CSharp.CSharpCodeGenerator.Compile(CompilerParameters options, String compilerDirectory, String compilerExe, String arguments, String& outputFile, Int32& nativeReturnValue, String trueArgs)
   at System.Xml.Serialization.XmlSerializer..ctor(Type type)

You can see that the XML serializer needs to invoke the C# compiler to dynamically compile some code.  The compiler needs to place all environment variables in a case-insensitive dictionary (since that's how things are done on Windows!).  Decompiling System.CodeDom.Compiler.Executor.ExecWaitWithCaptureUnimpersonated gives this:

        StringDictionary sd = new StringDictionary();
        foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
            sd.Add((string) entry.Key, (string) entry.Value);

Note that StringDictionary is case insensitive, according to the docs: "The key is handled in a case-insensitive manner; it is translated to lowercase before it is used with the string dictionary."  So that's why it crashes.

The big problem as I see it is that Cygwin, out-of-the-box, creates an environment block that violates a basic assumption of Windows programs - that the environment block is not case sensitive.  I don't know what the solution should be, but it's not this.

From /etc/profile:

tmp=$(cygpath -w "$ORIGINAL_TMP" 2> /dev/null)
temp=$(cygpath -w "$ORIGINAL_TEMP" 2> /dev/null)

This code is what causes the crash, by creating these "duplicate" (from a Windows perspective) keys.

I would guess that any Windows program that tries to do case-insensitive lookups in the environment is liable to crash.  At the very least, it won't necessarily give you the answer you expect (if both "TEMP" and "temp" store different values and you do a case insensitive lookup of "TeMp", which is going to be returned if you don't crash?)


--- Original message ---

Hi Cygwin, 

Many .Net programs that use to run correctly from a cygwin 1.7.9 console 
started throwing exceptions after updating to versions 1.7.10/1.7.11. I 
have noticed this problem on machines running Windows XP and Vista (32bits). 

I attach a very small example that triggers the bug. The example is 
written in C#, and requires the .Net framework versions 2.0 or 3.5. 

How to reproduce: 

1) Compile the example with 
         csc bug.cs 

     The c# compiler (csc), can be usually found in 
     or C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe 

2) Run the resulting bug.exe from a cygwin 1.7.10/1.7.11 console. It 
throws an exception. 

3) Run bug.exe from a native windows console (or a cygwin 1.7.9 
console). It runs without producing any output, and without throwing any 

Be aware that the bug is not triggered if the example is compiled with 
the .Net framework 4.0. 

Best regards, 
AndrÃs Martinelli 

ïusing System.Xml; 
using System.Xml.Schema; 
using System.Xml.Serialization; 

class Program { 
  static void Main(string[] args) { 
    XmlSerializer serializer = new XmlSerializer(typeof(Simple)); 

public class Simple : IXmlSerializable { 
  #region IXmlSerializable Members 
  public XmlSchema GetSchema() { return null; } 
  public void ReadXml(XmlReader reader) { } 
  public void WriteXml(XmlWriter writer) { } 

Problem reports:
Unsubscribe info:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]