未加星标

InvalidDataException in Process.GetProcesses

字体大小 | |
[系统(linux) 所属分类 系统(linux) | 发布者 店小二05 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏

Consider the following program:

public static void Main(string[] args) { try { Process.GetProcesses(); } catch (Exception e) { Console.WriteLine(e); } }

It seems that all the exception should be caught. However, sometimes I had the following exception on linux with dotnet cli-1.0.0-preview2 :

$ dotnet run System.IO.InvalidDataException: Found invalid data while decoding. at System.IO.StringParser.ParseNextChar() at Interop.procfs.TryParseStatFile(String statFilePath, ParsedStat& result, ReusableTextReader reusableReader) at System.Diagnostics.ProcessManager.CreateProcessInfo(ParsedStat procFsStat, ReusableTextReader reusableReader) at System.Diagnostics.ProcessManager.CreateProcessInfo(Int32 pid, ReusableTextReader reusableReader) at System.Diagnostics.ProcessManager.GetProcessInfos(String machineName) at System.Diagnostics.Process.GetProcesses(String machineName) at System.Diagnostics.Process.GetProcesses() at DotNetCoreConsoleApplication.Program.Main(String[] args) in /home/akinshin/Program.cs:line 12

How does it possible?

Preamble

I'm a guy who writes unit testing support in Rider . And it works fine with classic unit tests on the full .NET framework and mono. I know that there are many bugs here (Rider is still in the EAP stage), but at least it works: you can discover tests, run them, and even debug them. However, we also have to support new dotnet cli test toolchain. And there are many troubles with coreclr (probably because it is also in the preview stage). Even if our communication logic with dotnet test works on windows, it doesn't mean that it works on Linux and MacOS. Today I want to tell you a story about one bug investigation. In fact, we have a lot of such stories, but this one is in my favorite bug list. This story happened in October 2016, so I will tell you about dotnet cli-1.0.0-preview2 (in preview4 bug was fixed).

Situation

Do you know, what happens when you click 'Run' on a unit test from a modern C# project (e.g. based on project.json) in Rider? It starts a new process like this:

$ dotnet test --port 36513 --parentProcessId 3624 --no-build --framework net451

And it works perfectly on Windows. On Linux, I had the following exception:

dotnet-test Error: 0 : System.IO.InvalidDataException: Found invalid data while decoding. at System.IO.StringParser.ParseNextChar() at Interop.procfs.TryParseStatFile(String statFilePath, ParsedStat& result, ReusableTextReader reusableReader) at System.Diagnostics.ProcessManager.CreateProcessInfo(ParsedStat procFsStat, ReusableTextReader reusableReader) at System.Diagnostics.ProcessManager.CreateProcessInfo(Int32 pid, ReusableTextReader reusableReader) at System.Diagnostics.ProcessManager.GetProcessInfos(String machineName) at System.Diagnostics.Process.GetProcesses(String machineName) at System.Diagnostics.Process.GetProcesses() at Microsoft.DotNet.Tools.Test.TestCommand.RegisterForParentProcessExit(Int32 id) at Microsoft.DotNet.Tools.Test.TestCommand.DoRun(String[] args) Investigation

It seems that the problem is in Process.GetProcesses() . It was easy to write a minimal repro which produces this bug (you can find it at the beginning of the post). Usually, I do a final check for such bugs in a sterile environment: I close all the application and run it from the terminal. Guess what? My little program works without any exception now. Hmmm... Ok, open this wonderful program in Rider and run it: the InvalidDataException is in his place. Hmmm... Ok, another experiment: keep Rider opened and run the program from the terminal: we again see InvalidDataException . Huh! It seems that if we want to reproduce the bug, we have to run the program while Rider is running too.

At this point, I decided to create an issue on GitHub: dotnet/corefx#12755 . Thanks to @stephentoub , he helped me to understand what is going on here.

Explanation

Rider is based on the IntelliJ platform and ReSharper . So, we have two main processes: a JVM process and a CLR process. The name if the CLR process is JetBrains.ReSharper.Host.exe which includes a lot of threads. ReSharper is very complicated multithreading application, and we have own pool of threads (which one has the own name). Here is a bug explanation by @stephentoub :

The JetBrains.ReSharper.Host.exe process has a thread in it with a name that includes spaces: "JetPool (S) Reg". When we're parsing the processes' task list looking for its threads, we parse the stat file for each task, and in doing so, we misinterpret the space in the name as a space separator for the other items in the line. The fix in System.Diagnostics.Process is likely to track the parens and ensure we treat the whole parenthesized unit as the name. In the meantime, as a workaround, if you have control over the thread/task's name (something somewhere is probably calling a function like pthread_setname_np, or using prctl with PR_SET_NAME), you could try using a name that doesn't include spaces.

Workaround

Now the bug if fixed, it is a part of .NET Core 2.0 and dotnet cli 1.0.0-preview4 . However, many people still use dotnet cli 1.0.0-preview2 and Rider should support it for some time. We came up with a workaround which allows running unit tests with preview2: we just don't specify --parentProcessId on Linux/MacOS:

var commonArgs = string.Format("test --port {0} --no-build{1}", server.PortNumber, frameworkArg); var windowsArgs = string.Format("test --port {0} --parentProcessId {1} --no-build{2}", server.PortNumber, Process.GetCurrentProcess().Id, frameworkArg); var args = PlatformUtil.IsRunningUnderWindows ? windowsArgs : commonArgs;

In this case, dotnet doesn't call Process.GetProcesses() and everything works fine. Rider is able to establish a connection even when the --parentProcessId parameter is omitted.

Of course, we also can rename our threads, but I wanted to fix the bug without any changes in the ReSharper core libraries.

Conclusion

In Rider, we should support many bleeding edge technologies which contain a lot of bugs. Hopefully, a big part of such technologies will die soon (and will be replaced by stable version). However, people can't update all their projects on the same day with the next release of its dependencies. So, we have to maintain a lot of hacks and ugly pieces of code for a several months after the date when another preview was released. It's not easy, and it conflicts with our sense of beauty, but we still try to do everything to make our users happy regardless of which version of runtime they use.

Links dotnet/corefx#12755: InvalidDataException in Process.GetProcesses on Linux dotnet/corefx#12791: Fix parsing of procfs stat files when comm name contains spaces dotnet/corefx#12834: Linux: System.Diagnostics.Process.GetProcesses can throw if reading from /proc for any process fails dotnet/cli#4452: "dotnet test" crashes if another process or thread has a name with a space Share:

本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统

主题: LinuxWindowsMacOSGitC#JVMGitHubGuess
分页:12
转载请注明
本文标题:InvalidDataException in Process.GetProcesses
本站链接:http://www.codesec.net/view/532114.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 系统(linux) | 评论(0) | 阅读(23)