花费时间编写一些重要的bash脚本后,较新版本的Cygwin已经破坏了它们。这些脚本调用不与Cygwin链接的本地Win32应用程序,这显然不是Cygwin官方支持的。
这让我感到惊讶,因为多年来我一直以为Cygwin可以在混合环境中使用,结合本地非Cygwin Win32应用程序和使用Cygwin兼容性层的POSIX程序。但是显然只有POSIX兼容性层得到真正支持,如果本地Win32非Cygwin应用程序工作,则被认为是一个幸运的巧合。
我从在Cygwin内运行针对.NET Framework编译的程序时遇到的不兼容性中发现了这一点。这以前可以正常工作,但几个月前就出了问题。具体而言,将输出从.NET程序管道化到任何其他Win32程序的标准输入通常会导致接收Win32程序获得过早的文件结束信号,因为Cygwin最近几个月切换到消息管道而不是字节管道 - 而且消息管道似乎与使用Visual C ++或.NET Framework的任何接收应用程序不兼容。这是因为.NET向标准输出发出空写入,只有在使用消息管道时才会传递给接收应用程序。接收应用程序成功读取零字节,因此认为它是文件末尾。项目负责人似乎并不认为这是一个真正的问题,因为他们显然不支持从Cygwin内运行非Cygwin程序(惊喜!)。
引用邮件列表中的项目负责人Christopher Faylor的多个电子邮件:您所看到的问题可能是因为几个版本前Cygwin更改为使用消息类型管道导致的。这种情况不会改变。这个变化是为了解决Cygwin程序的问题,而这些程序显然是我们的首要任务。
无论有多少人使用Visual C++或.NET,他们都不是我们的目标受众。对于不想使用UNIX工具的人,事情能够顺利进行是很好的,但他们并不是我们的主要关注重点。修复那些想要使用非Cygwin内容的人的问题不是我认为高优先级的事情。
从pipe.cc中可以看出:请注意,将管道的写端作为PIPE_TYPE_MESSAGE打开。这似乎更接近Linux管道的行为,并且绝对需要用于pty处理,因为当指定CANON模式时,fhandler_pty_master将以块形式写入数据,以换行符结尾。上面的评论展示了这里的“和”关系。消息类型管道更接近于模仿Linux(UNIX)管道的行为,并且绝对需要用于pty。
我同意James的观点:运行时可能存在错误,但我也同意Cygwin应该能够处理这些场景。
你们之间的完全一致不会有太大的影响。通过投票无法改变Cygwin源代码。
即使最终修复了此问题,他们在三个月内可能会破坏另外一些东西,并且不关心修复回归问题。他们可能会考虑一个补丁,但我需要花费相当长的时间来找出一个有效的解决方案。因为他们显然非常愿意破坏与本地Win32应用程序的兼容性,所以我认为我的时间更好地花在其他地方。所以,Cygwin不应被视为混合Win32 / Cygwin环境的稳定平台-我的替代选择是什么?我从不使用除基本Cygwin安装程序和一些基本Perl脚本之外的任何内容。
更新:在发布了这个原始问题后,他们最终在CYGWIN环境变量中引入了一个新的管道字节标志:请查看文档。如果设置了此标志,它将解决上述问题。在调用非Cygwin Win32程序时,一定要确保设置了pipe_byte标志。
但是,我后来发现.NET Framework 4.0与Cygwin不兼容。以前版本的.NET Framework没有这个问题。我在Cygwin邮件列表中首先提到了这个问题。
Cygwin和.NET Framework 4.0之间的管道同步问题
在没有得到有效的回复后,我进一步调查发现Cygwin正在创建重叠管道,这导致了问题。请注意,在使用具有重叠管道的非重叠Win32 API调用是未定义的,并且大多数(全部?)Win32非Cygwin程序不使用其标准文件句柄的重叠I/O。我提交了一个补丁,在CYGWIN
环境变量中创建了一个pipe_nooverlap
标志,以防止发生这种情况:
不幸的是,他们拒绝了该补丁,因此您将永远看不到它出现在主要的Cygwin DLL中:
Re: Patch to optionally disable overlapped pipes
拒绝该补丁的原因如下:
- 暗示我破坏了Cygwin的信号实现;但是,我发现情况并非如此,因为信号仍然使用重叠管道。
- 他们不想添加一个环境变量标志,尽管它显然可以解决问题。
- 他们不想支持甚至具有非重叠管道选项的代码。
有了这样的理由和态度,我恐怕无法想出任何改变补丁以满足其要求的方法...他们似乎决心永远禁止使用非重叠管道。我已经使用该补丁一段时间了,并且没有遇到任何问题。此外,我无法想象任何可能破坏pipe_nooverlap
标志的情况(请参见我在其邮件列表上的后续电子邮件),但我将其保留为标志以防万一出现问题。
因此,如果您想从Cygwin调用非Cygwin Win32或.NET Framework程序,则需要执行以下操作:
- 将我的补丁应用于您正在使用的任何Cygwin版本的源代码。不要指望这个补丁会出现在未来的Cygwin版本中。
- 在
CYGWIN
环境变量中设置pipe_byte
和pipe_nooverlap
标志。
目前这样可以解决问题!我发布此信息,以帮助任何仍然希望在某些方面使用Cygwin的人。