IronRuby の Runtime Error と スタックトレース

| コメント(0) | トラックバック(0) このエントリーを含むはてなブックマーク

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に渡し取得する必要がある。 これはまた別の機会にでも。

トラックバック(0)

トラックバックURL: http://www.m-tea.info/mt-tb.cgi/62

コメントする

あわせて読みたいブログパーツ

このブログ記事について

このページは、k1ha410が2010年1月10日 18:04に書いたブログ記事です。

ひとつ前のブログ記事は「Azure の IISからIronRuby」です。

次のブログ記事は「Ruby 1.8.6 のインストール」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。