結束了,我有以下程序(全部源):應用程序運行,但最終還是以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
錯誤。
我已經試過......嗯,除了從FileInfo
和UnixFileInfo
沒有來回切換,問題是,我不知道是什麼,甚至嘗試。
這是我第一個針對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
是什麼讓我的應用程序最終結束了一個SIGSEGV
或System.NullReferenceException
示數了呢?