2014-12-03 19 views
0

結束了,我有以下程序(全部源):應用程序運行,但最終還是以SIGSEGV或NullReferenceException異常

using Mono.Unix; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.IO; 
using System.Linq; 
using System.Text.RegularExpressions; 
using System.Threading; 

namespace StoneOS.ResourceMonitor 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var runner = new Timer(state => 
      { 
       var cpu = CPUUsage(); 
       var ram = RAMUsage(); 
       var hdd = DriveUsage("/dev/sda3"); 

       Console.WriteLine("[{0:O}] C: {1:N2} | R: {2:N2} | S: {3:N2} | H: {4:N2}", DateTime.Now, cpu, ram.Total, ram.Swap, hdd); 
      }, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(50)); 

      Console.ReadKey(true); 
     } 

     private static string LastReadCPULine = null; 

     struct Jiffy 
     { 
      public double Total; 

      public double Work; 
     } 

     public static double? CPUUsage() 
     { 
      // File path and descriptor, that holds the actual CPU data. 
      var statsFile = "/proc/stat"; 
      // var unixInfo = new FileInfo(statsFile); 
      var unixInfo = new UnixFileInfo(statsFile); 

      // Read last queried data into cache. 
      string last = LastReadCPULine; 

      // Prepare for new read. 
      List<string> output = new List<string>(); 

      // Read data. 
      using (var reader = new StreamReader(unixInfo.OpenRead())) 
      { 
       string currentLine; 

       while ((currentLine = reader.ReadLine()) != null) 
       { 
        output.Add(currentLine); 
       } 
      } 

      unixInfo = null; // clear... 

      // Select the first entry, that should be total of CPU. 
      string current = LastReadCPULine = output.First(); 

      // If there was no last entry, that means we cannot calculate - return zero. 
      if (last == null) 
      { 
       return null; 
      } 

      return CalculateCPUUsage(last, current); 
     } 

     private static double CalculateCPUUsage(string last, string current) 
     { 
      Jiffy lastJiffy = GetJiffies(last); 
      Jiffy currentJiffy = GetJiffies(current); 

      double work = currentJiffy.Work - lastJiffy.Work; 
      double total = currentJiffy.Total - lastJiffy.Total; 

      return (work/total) * 100; 
     } 

     private static Jiffy GetJiffies(string statLine) 
     { 
      // Split on spaces. 
      string[] parts = subsequentSpacePattern.Split(statLine); 

      // Remove first entry (label - cpu). 
      IEnumerable<double> convertedData = parts.Skip(1).Select(entry => Convert.ToDouble(entry)); 

      // Calculate the values for the Jiffy. 
      return new Jiffy 
      { 
       Total = convertedData.Sum(), 
       Work = convertedData.Take(3).Sum() 
      }; 
     } 

     struct Memory 
     { 
      public double Total; 
      public double Swap; 
     } 

     private static Memory RAMUsage() 
     { 
      var processInfo = new ProcessStartInfo("/bin/free", "-b") 
      { 
       RedirectStandardError = true, 
       RedirectStandardInput = true, 
       RedirectStandardOutput = true, 
       UseShellExecute = false, 
       CreateNoWindow = true 
      }; 

      List<string> output = new List<string>(); 

      using (var process = Process.Start(processInfo)) 
      { 
       process.WaitForExit(); 

       string currentLine; 

       using (var reader = process.StandardOutput) 
       { 
        while ((currentLine = reader.ReadLine()) != null) 
        { 
         output.Add(currentLine); 
        } 
       } 
      } 

      return new Memory 
      { 
       Total = CalculateTotalMemoryUsage(output.Skip(1).Take(1).Single()), 
       Swap = CalculateSwapUsage(output.Skip(2).Take(1).Single()) 
      }; 
     } 

     private static Regex subsequentSpacePattern = new Regex(@"\s+"); 

     private static double CalculateTotalMemoryUsage(string memoryLine) 
     { 
      string[] parts = subsequentSpacePattern.Split(memoryLine); 

      // Console.WriteLine("[{0:O}] Memory: {1}", DateTime.Now, memoryLine); 
      // Console.WriteLine("[{0:O}] Memory: {1}", DateTime.Now, String.Join(", ", parts)); 

      string totalByteString = parts.Skip(1).Take(1).Single(); 
      string availableByteString = parts.Last(); 

      // Console.WriteLine("[{0:O}] Total: '{1}'; Available: '{2}'", DateTime.Now, totalByteString, availableByteString); 

      double total = Convert.ToDouble(totalByteString); 
      double available = Convert.ToDouble(availableByteString); 

      var percentage = (available/total) * 100d; 

      // Console.WriteLine("[{0:O}] Memory %: {1} (Total: {2}, Free: {3})", DateTime.Now, percentage, total, available); 

      return 100d - percentage; 
     } 

     private static double CalculateSwapUsage(string swapLine) 
     { 
      string[] parts = subsequentSpacePattern.Split(swapLine); 

      // Console.WriteLine("[{0:O}] Swap: {1}", DateTime.Now, swapLine); 
      // Console.WriteLine("[{0:O}] Swap: {1}", DateTime.Now, String.Join(", ", parts)); 

      string totalByteString = parts.Skip(1).Take(1).Single(); 
      string freeByteString = parts.Last(); 

      // Console.WriteLine("[{0:O}] Total: '{1}'; Free: '{2}'", DateTime.Now, totalByteString, freeByteString); 

      double total = Convert.ToDouble(totalByteString); 
      double free = Convert.ToDouble(freeByteString); 

      var percentage = (free/total) * 100d; 

      // Console.WriteLine("[{0:O}] Swap %: {1} (Total: {2}, Free: {3})", DateTime.Now, percentage, total, free); 

      // We are interested in remainder. 
      return 100d - percentage; 
     } 

     private static Regex multiSpacePattern = new Regex(@"\s+"); 

     private static double DriveUsage(string drive) 
     { 
      var processInfo = new ProcessStartInfo("/bin/df", String.Format("-B1 {0}", drive)) 
      { 
       RedirectStandardError = true, 
       RedirectStandardInput = true, 
       RedirectStandardOutput = true, 
       UseShellExecute = false, 
       CreateNoWindow = true 
      }; 

      List<string> output = new List<string>(); 

      using (var process = Process.Start(processInfo)) 
      { 
       process.WaitForExit(); 

       string currentLine; 

       using (var reader = process.StandardOutput) 
       { 
        while ((currentLine = reader.ReadLine()) != null) 
        { 
         output.Add(currentLine); 
        } 
       } 
      } 

      // Second output line is the one we're looking for. 
      var second = output.Last(); 

      string[] parts = multiSpacePattern.Split(second); 

      if (parts.Length != 6) 
      { 
       throw new ApplicationException(String.Format("Invalid column count in df's output: {0}", second)); 
      } 

      var percentage = parts[4].TrimEnd('%'); 

      // Console.WriteLine("Output: {0}", second); 
      // Console.WriteLine("[4] = {0}, percentage = {1}", parts[4], percentage); 

      return Convert.ToDouble(percentage); 
     } 
    } 
} 

只是一個基本的資源監視器,讀取/從系統和報告每N請求的一些信息秒。這用於反映實際應用程序中發生的錯誤。這發生在與實際應用程序相同的錯誤。爲了調試目的,週期間隔設置得較高以更快地得到錯誤。

如圍繞線41 & 42分別可以看出,:

// var unixInfo = new FileInfo(statsFile); 
var unixInfo = new UnixFileInfo(statsFile); 

我已成立了兩個解決方案。一個利用本身.NET/Mono本身,另一個 - Mono.Posix

通過使用本地解決方案(FileInfo)運行時 - 沒有問題,一切都按預期工作。

現在,當與Mono.Posix等效(UnixFileInfo)運行時,軟件最終會以System.NullReferenceException甚至更​​糟 - SIGSEGV結束。

System.NullReferenceException情況:

Unhandled Exception: 
System.NullReferenceException: Object reference not set to an instance of an object 
    at System.String.IndexOfAnyUnchecked (System.Char[] anyOf, Int32 startIndex, Int32 count) [0x00000] in :0 
    at System.String.IndexOfAny (System.Char[] anyOf) [0x00019] in /build/mono/src/mono-3.10.0/mcs/class/corlib/System/String.cs:896 
    at Mono.Unix.UnixPath.CheckPath (System.String path) [0x00000] in :0 
    at Mono.Unix.UnixFileSystemInfo..ctor (System.String path) [0x00000] in :0 
    at Mono.Unix.UnixFileInfo..ctor (System.String path) [0x00000] in :0 
    at StoneOS.ResourceMonitor.Program.CPUUsage() [0x00008] in /home/stone/sandbox/StoneOS.ResourceMonitor/StoneOS.ResourceMonitor/Program.cs:44 
    at StoneOS.ResourceMonitor.Program.m__0 (System.Object state) [0x00001] in /home/stone/sandbox/StoneOS.ResourceMonitor/StoneOS.ResourceMonitor/Program.cs:20 
    at System.Threading.Timer+Scheduler.TimerCB (System.Object o) [0x00007] in /build/mono/src/mono-3.10.0/mcs/class/corlib/System.Threading/Timer.cs:317

SIGSEGV情況:

Stacktrace: 


Native stacktrace: 

     /usr/lib/libmonosgen-2.0.so.1(+0xd546a) [0x7f2d9851f46a] 
     /usr/lib/libmonosgen-2.0.so.1(+0x133aeb) [0x7f2d9857daeb] 
     /usr/lib/libmonosgen-2.0.so.1(+0x3fde6) [0x7f2d98489de6] 
     /usr/lib/libpthread.so.0(+0x10200) [0x7f2d9823e200] 
     /usr/lib/libmonosgen-2.0.so.1(+0x204d70) [0x7f2d9864ed70] 
     /usr/lib/libmonosgen-2.0.so.1(+0x20bd4f) [0x7f2d98655d4f] 
     /usr/lib/libmonosgen-2.0.so.1(+0x20c159) [0x7f2d98656159] 
     /usr/lib/libmonosgen-2.0.so.1(+0x229cb3) [0x7f2d98673cb3] 
     /usr/lib/libmonosgen-2.0.so.1(+0x229d7f) [0x7f2d98673d7f] 
     [0x4150ff33] 

Debug info from gdb: 

warning: File "/usr/bin/mono-sgen-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load". 
To enable execution of this file add 
     add-auto-load-safe-path /usr/bin/mono-sgen-gdb.py 
line to your configuration file "/root/.gdbinit". 
To completely disable this security protection add 
     set auto-load safe-path/
line to your configuration file "/root/.gdbinit". 
For more information about this security protection see the 
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell: 
     info "(gdb)Auto-loading safe path" 
warning: Could not load shared library symbols for linux-vdso.so.1. 
Do you need "set solib-search-path" or "set sysroot"? 
[New LWP 441] 
[New LWP 440] 
[New LWP 439] 
[New LWP 438] 
[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/usr/lib/libthread_db.so.1". 
0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 
    Id Target Id   Frame 
    5 Thread 0x7f2d95c9b700 (LWP 438) "Finalizer" 0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 
    4 Thread 0x7f2d956ff700 (LWP 439) "Timer-Scheduler" 0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 
    3 Thread 0x7f2d954fe700 (LWP 440) "Threadpool moni" 0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 
    2 Thread 0x7f2d954bd700 (LWP 441) "Threadpool work" 0x00007f2d9823ddeb in waitpid() from /usr/lib/libpthread.so.0 
* 1 Thread 0x7f2d98c48780 (LWP 437) "mono" 0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 

Thread 5 (Thread 0x7f2d95c9b700 (LWP 438)): 
#0 0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 
#1 0x00007f2d9864cd46 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#2 
#3 0x00007f2d9823c90e in sem_wait() from /usr/lib/libpthread.so.0 
#4 0x00007f2d986ab5c6 in mono_sem_wait() from /usr/lib/libmonosgen-2.0.so.1 
#5 0x00007f2d98624529 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#6 0x00007f2d986069e7 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#7 0x00007f2d986b0dd5 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#8 0x00007f2d98235314 in start_thread() from /usr/lib/libpthread.so.0 
#9 0x00007f2d97f733ed in clone() from /usr/lib/libc.so.6 

Thread 4 (Thread 0x7f2d956ff700 (LWP 439)): 
#0 0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 
#1 0x00007f2d9864cd46 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#2 
#3 0x00007f2d9823ac68 in [email protected]@GLIBC_2.3.2() from /usr/lib/libpthread.so.0 
#4 0x00007f2d986885ba in ??() from /usr/lib/libmonosgen-2.0.so.1 
#5 0x00007f2d9869c9c2 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#6 0x00007f2d9860642f in ??() from /usr/lib/libmonosgen-2.0.so.1 
#7 0x00007f2d986078dc in ??() from /usr/lib/libmonosgen-2.0.so.1 
#8 0x000000004152a6ad in ??() 
#9 0x0000000000000001 in ??() 
#10 0x0000000000000001 in ??() 
#11 0x0000000000000032 in ??() 
#12 0x00007f2d97002cd0 in ??() 
#13 0x0000000000000031 in ??() 
#14 0x00007f2d880025e0 in ??() 
#15 0x00007f2d956febb0 in ??() 
#16 0x00007f2d956fe9f0 in ??() 
#17 0x00007f2d956fe950 in ??() 
#18 0x000000004152a418 in ??() 
#19 0x0000000000000000 in ??() 

Thread 3 (Thread 0x7f2d954fe700 (LWP 440)): 
#0 0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 
#1 0x00007f2d9864cd46 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#2 
#3 0x00007f2d97f802ca in clock_nanosleep() from /usr/lib/libc.so.6 
#4 0x00007f2d9869df48 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#5 0x00007f2d98609abe in ??() from /usr/lib/libmonosgen-2.0.so.1 
#6 0x00007f2d986069e7 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#7 0x00007f2d986b0dd5 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#8 0x00007f2d98235314 in start_thread() from /usr/lib/libpthread.so.0 
#9 0x00007f2d97f733ed in clone() from /usr/lib/libc.so.6 

Thread 2 (Thread 0x7f2d954bd700 (LWP 441)): 
#0 0x00007f2d9823ddeb in waitpid() from /usr/lib/libpthread.so.0 
#1 0x00007f2d9851f500 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#2 0x00007f2d9857daeb in ??() from /usr/lib/libmonosgen-2.0.so.1 
#3 0x00007f2d98489de6 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#4 
#5 0x00007f2d9864ed70 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#6 0x00007f2d98655d4f in ??() from /usr/lib/libmonosgen-2.0.so.1 
#7 0x00007f2d98656159 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#8 0x00007f2d98673cb3 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#9 0x00007f2d98673d7f in ??() from /usr/lib/libmonosgen-2.0.so.1 
#10 0x000000004150ff33 in ??() 
#11 0x00007f2d973fffa0 in ??() 
#12 0x00007f2d973ff108 in ??() 
#13 0x000000000000001d in ??() 
#14 0x00007f2d973ff108 in ??() 
#15 0x0000000000000001 in ??() 
#16 0x00007f2d800025e0 in ??() 
#17 0x000000000000001f in ??() 
#18 0x00007f2d954bc6d0 in ??() 
#19 0x00007f2d954bc5e0 in ??() 
#20 0x0000000041557efc in ??() 
#21 0x00007f2d97000d30 in ??() 
#22 0x00007f2d973fffa0 in ??() 
#23 0x00007f2d973f1ae8 in ??() 
#24 0x000000000000001f in ??() 
#25 0x0000000000000001 in ??() 
#26 0x000000000000001d in ??() 
#27 0x00007f2d954bd680 in ??() 
#28 0x00007f2d98673d3f in ??() from /usr/lib/libmonosgen-2.0.so.1 
#29 0x000000004150ff33 in ??() 
#30 0x00007f2d97000d30 in ??() 
#31 0x00007f2d973f1ae8 in ??() 
#32 0x0000000000000001 in ??() 
#33 0x0000000000000025 in ??() 
#34 0x00007f2d973f1ae8 in ??() 
#35 0x00007f2d97000d30 in ??() 
#36 0x00007f2d973f1ae8 in ??() 
#37 0x00007f2d97000d30 in ??() 
#38 0x00007f2d954bc770 in ??() 
#39 0x00000000415577e4 in ??() 
#40 0x000000000000001f in ??() 
#41 0x0000000000000001 in ??() 
#42 0x0000000000000001 in ??() 
#43 0x000000000000001c in ??() 
#44 0x0000000000000001 in ??() 
#45 0x0000000000000025 in ??() 
#46 0x000000000000001f in ??() 
#47 0x0000000000000001 in ??() 
#48 0x0000000000000001 in ??() 
#49 0x00007f2d973f1ae8 in ??() 
#50 0x00007f2d973fffa0 in ??() 
#51 0x0000000000000000 in ??() 

Thread 1 (Thread 0x7f2d98c48780 (LWP 437)): 
#0 0x00007f2d97ebed57 in sigsuspend() from /usr/lib/libc.so.6 
#1 0x00007f2d9864cd46 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#2 
#3 0x00007f2d9823d3bb in read() from /usr/lib/libpthread.so.0 
#4 0x00007f2d986897e1 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#5 0x00007f2d985ac234 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#6 0x0000000041530c61 in ??() 
#7 0x00007f2d970168c0 in ??() 
#8 0x0000000000000000 in ??() 

================================================================= 
Got a SIGSEGV while executing native code. This usually indicates 
a fatal error in the mono runtime or one of the native libraries 
used by your application. 
================================================================= 

Aborted (core dumped)

大部分的時間,不過,它的SIGSEGV錯誤。

我已經試過......嗯,除了從FileInfoUnixFileInfo沒有來回切換,問題是,我不知道是什麼,甚至嘗試

這是我第一個針對Linux的主要Mono應用程序,因此不知道該在這裏做什麼。

我已經通過Mono GDB debugging guide走 - 成立提供.gdbinit,跑了gdb - 結果:

Program received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0x7ffff47fe700 (LWP 4558)] 
0x00007ffff7a1cc47 in ??() from /usr/lib/libmonosgen-2.0.so.1 
(gdb) mono_backtrace 15 
#0 0x00007ffff7a1cc47 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#1 0x00007ffff7a1caf8 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#2 0x00007ffff79f236d in ??() from /usr/lib/libmonosgen-2.0.so.1 
#3 0x00007ffff79f7725 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#4 0x00007ffff79f8159 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#5 0x00007ffff7a15cb3 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#6 0x00007ffff7a15ed4 in ??() from /usr/lib/libmonosgen-2.0.so.1 
#7 0x00007ffff79cdb16 in mono_array_new_specific() 
    from /usr/lib/libmonosgen-2.0.so.1 
#8 0x400135cb in Cannot access memory at address 0xffffffffe00f2410

這給什麼東西默認mono --debug <path/to/exe>不 - 的mono_array_new_specific()通話,雖然,我不知道它在這裏有什麼相關性。

我不確定這是否是Mono.Posix庫中的一個錯誤,或者是其他的錯誤,但是這真的讓我感到困擾。是的,對於這個特殊的例子,我可以逃脫FileInfo,但在真正的應用程序中,我實際上正在使用UnixSymbolicLinkInfo這導致了同樣的問題。

mono -V

Mono JIT compiler version 3.10.0 (tarball Mon Oct 6 20:46:04 UTC 2014) 
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com 
     TLS:   __thread 
     SIGSEGV:  altstack 
     Notifications: epoll 
     Architecture: amd64 
     Disabled:  none 
     Misc:   softdebug 
     LLVM:   supported, not enabled. 
     GC:   sgen 

是什麼讓我的應用程序最終結束了一個SIGSEGVSystem.NullReferenceException示數了呢?

回答

0

NullReferenceException不應該發生在類庫(System.String類)中,所以這必須是一個bug。請在http://bugzilla.xamarin.com/報告。理想情況下,在調用方法IndexOfAny()時,您應該在報告中包含使用的字符串和使用的參數。爲此,您可能需要檢查Mono.Posix的源代碼,以查看Mono.Unix.UnixPath.CheckPath()中的內容。

相關問題