IronRubyのスクリプトを C# から呼び出していて、Rubyソースにバグがあり例外が発生した際、そのままではトレースできない。
どのようにトレースするかについて、まとめてみる。
IronRuby Scriptのエラー
例えば以下のようなプログラムを実行すると、以下のような実行結果が得られる
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Run3();
Console.ReadLine();
}
private static void Run3()
{
var engine = IronRuby.Ruby.CreateEngine();
var src = @"
hash = Hash.new
hash['abc'] = 123
puts ahsh['abc']
";
var source = engine.CreateScriptSourceFromString(src);
var scope = engine.CreateScope();
scope.SetVariable("k2", "abc");
try
{
source.Execute(scope);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
}
undefined method `ahsh' for main:Object 場所 Microsoft.Scripting.Interpreter.ThrowInstruction.Run(InterpretedFrame frame) 場所 Microsoft.Scripting.Interpreter.Interpreter.RunInstructions(InterpretedFrame frame) 場所 Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame) 場所 Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1) 場所 IronRuby.Runtime.RubyScriptCode.Run(Scope scope, Boolean bindGlobals) 場所 IronRuby.Runtime.RubyScriptCode.Run(Scope scope) 場所 Microsoft.Scripting.SourceUnit.Execute(Scope scope, ErrorSink errorSink) 場所 Microsoft.Scripting.SourceUnit.Execute(Scope scope) 場所 Microsoft.Scripting.Hosting.ScriptSource.Execute(ScriptScope scope) 場所 ConsoleApplication1.Program.Run3() 場所 Visual Studio 2008\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:行 28
これは、「hash」を typo して「ahsh」としてしまったために発生しているのである。 この短さであれば、原因は簡単に分かるが、このスタックトレースからだと分かりにくい。
せめて、rubyスクリプトのコールスタックが出てくれないと困るという事で 以下のようにする。
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Run4();
Console.ReadLine();
}
private static void Run4()
{
var engine = IronRuby.Ruby.CreateEngine();
var src = @"
hash = Hash.new
hash['abc'] = 123
puts ahsh['abc']
";
var source = engine.CreateScriptSourceFromString(src);
var scope = engine.CreateScope();
scope.SetVariable("k2", "abc");
try
{
source.Execute(scope);
}
catch (Exception e)
{
var rubyexception = IronRuby.Runtime.RubyExceptionData.GetInstance(e);
Console.WriteLine(e.Message);
foreach (var l in rubyexception.Backtrace)
{
Console.WriteLine(l.ToString());
}
}
}
}
}
このようにすると、以下のような ruby 風のスタックトレースが取れる。
undefined method `ahsh' for main:Object :0 c:\Documents\Visual Studio 2008\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:28:in `Run4' c:\Documents\Visual Studio 2008\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:9:in `Main' mscorlib:0:in `_nExecuteAssembly' mscorlib:0:in `ExecuteAssembly' Microsoft.VisualStudio.HostingProcess.Utilities:0:in `RunUsersAssembly' mscorlib:0:in `ThreadStart_Context' mscorlib:0:in `Run' mscorlib:0:in `ThreadStart'
このスタックトレースだと、さほど変わらないように思えるかもしれないが、これが 複数のライブラリ等を利用するようになると、非常に重要である。
補足
IronPythonでは、「ScriptingRuntimeHelpers.GetDynamicStackFrames」で取得出来るらしいが、 IronRubyでは現在(2010/01/10)利用できないようである。
おわりに
IronRubyの実行時エラーについて取得する方法について書いたが、実は スクリプトのパースエラーについても取得できないといけない。
これは、ErrorListener をScriptSource.Compileに渡し取得する必要がある。 これはまた別の機会にでも。


コメントする