7 Replies Latest reply: Apr 15, 2011 11:17 AM by 853537 RSS

    OO4Oのスレッドセーフについて

    853537
      ※書きこみ先が違っていたらごめんなさい

      現在、OO4O(バージョン5)を使用してWebアプリの開発をしています。

      IIS上で稼働させている状態で
      ハングしてしまう状況が発生しました。

      AdPlusでDumpログを取得し、
      Debug Diagnostics Toolでログを解析したところ、
      以下のような内容が出力されました。

      エラーの発生個所は
      OraSession.GetDatabaseFromPool(10)
      のようです。

      Googleで検索をすると、
      スレッド間でデッドロックになっているのでは?
      という回答が目に付いたので
      どのように修正するか悩んでいます。

      OO4Oはスレッドセーフだと思っているので
      こちらのコードの問題だと思うのですが、
      どうなのでしょうか?

      わかる方がいらっしゃいましたら教えてください。



      ====ここから===============================
      Detected a serious critical section related problem in FULLDUMP_HangMode_w3wp.exe__1330_2011-04-07_12-54-10-727_0e44.dmp
      Lock at 0x010e0aa8 is Orphaned
      Impact analysis
      100.00% of executing ASP Requests blocked
      78.29% of threads blocked
      (Threads 25 26 27 28 29 30 31 32 33 34 35 36 37 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126)
      The following functions are involved in the root cause
      oip10!DllUnregisterServer+724b6
      oip10!DllUnregisterServer+7297c
      oip10!DllUnregisterServer+72a80
      The following modules are involved in the root cause
      F:\oracle\product\10.2.0\client_1\bin\oip10.dll

      ↓スレッド25を参照すると

      Thread 25 - System ID 1408
      Entry point 0x00000000
      Create time 2011/04/07 7:13:15
      Time spent in user mode 0 Days 00:00:00.811
      Time spent in kernel mode 0 Days 00:00:00.312

      This thread is waiting on critical section 0x010e0aa8 which has been orphaned.

      Function Source
      ntdll!KiFastSystemCallRet
      ntdll!NtWaitForSingleObject+c
      ntdll!RtlpWaitOnCriticalSection+155
      ntdll!RtlEnterCriticalSection+152
      oip10!DllUnregisterServer+724b6
      oleaut32!CTypeInfo2::Invoke+23a
      oleaut32!DispInvoke+23
      oip10!DllUnregisterServer+3c68e
      vbscript!InvokeByName+42
      vbscript!CScriptRuntime::RunNoEH+22b2
      vbscript!CScriptRuntime::Run+62
      vbscript!CScriptEntryPoint::Call+51
      vbscript!CScriptRuntime::RunNoEH+1beb
      vbscript!CScriptRuntime::Run+62
      vbscript!CScriptEntryPoint::Call+51
      vbscript!CScriptRuntime::RunNoEH+1beb
      vbscript!CScriptRuntime::Run+62
      vbscript!CScriptEntryPoint::Call+51
      vbscript!CSession::Execute+c8
      vbscript!COleScript::ExecutePendingScripts+144
      vbscript!COleScript::SetScriptState+14d
      asp!CActiveScriptEngine::TryCall+19
      asp!CActiveScriptEngine::Call+e7
      asp!CallScriptFunctionOfEngine+3e
      asp!ExecuteRequest+148
      asp!Execute+1c1
      asp!CHitObj::ViperAsyncCallback+3f9
      asp!CViperAsyncRequest::OnCall+6a
      comsvcs!CSTAActivityWork::STAActivityWorkHelper+32
      ole32!EnterForCallback+cf
      ole32!SwitchForCallback+1a8
      ole32!PerformCallback+a3
      ole32!CObjectContext::InternalContextCallback+15b
      ole32!CObjectContext::DoCallback+1c
      comsvcs!CSTAActivityWork::DoWork+12f
      comsvcs!CSTAThread::DoWork+18
      comsvcs!CSTAThread::ProcessQueueWork+37
      comsvcs!CSTAThread::WorkerLoop+188
      msvcrt!_endthreadex+44
      msvcrt!_endthreadex+ce
      kernel32!BaseThreadInitThunk+e
      ntdll!__RtlUserThreadStart+23
      ntdll!_RtlUserThreadStart+1b

      ASP request executing on thread 25
      request for
      Request alive for 49 day(s) 15:03:43
      QueryString
      Request mapped to

      Script call stack for thread 25

      Function Scope Line Of Code Source File Line Number
      fncOpenDB Set objOradatabase = OraSession.GetDatabaseFromPool(10) 0
      fncGetUserInfo Call fncOpenDB() 0
      Global Scope Call fncGetUserInfo(strUSERCD, strUSERPASS, strUSERKUBUN, strZENSCD, strKENCD, strKENSCD, strJACD, strJASCD, strMCCD, strMCSCD, strNAME, strMAIL) 0
      ====ここまで===============================
        • 1. Re: OO4Oのスレッドセーフについて
          853537
          バージョンの記述ミスです。
          オラクルは10gを使用しています。すみません。
          • 2. Re: OO4Oのスレッドセーフについて
            830749
            断言できませんが、ログを見ると共有オブジェクトの所有権を取ろうとする時に親スレッドが
            先に落ちているように見えますね。
            オブジェクトの解放手順やスレッドの終了手順は正しいですか?
            もしかしたら複数スレッドで各セッションのオブジェクトを共有したりしてるとオブジェクトの
            解放が想定より遅れることがあるかもしれません。
            • 3. Re: OO4Oのスレッドセーフについて
              853537
              なるほど。
              終了処理を一通り洗ってみます。

              ところで、OraSessionですが、
              クラスはスレッドセーフだと思いますが、
              インスタンスのメソッドもスレッドセーフなんでしょうか?

              OraSessionをグローバル変数で定義しているので、
              こいつの前後でlockしてあげれば解決するのか?と思いまして・・・
              • 4. Re: OO4Oのスレッドセーフについて
                830749
                メソッド自体は各スレッドで独立して実行できますが、例えばDataset等のオブジェクトを共有するような場合は
                排他制御が必要である事を認識した実装になっているのであれば大丈夫だと思います。
                • 5. Re: OO4Oのスレッドセーフについて
                  853537
                  ※すみません。当方、VBScriptとOO4Oを初めて扱うので、
                   変な質問だったらごめんなさい。

                  オブジェトの解放についてですが、
                  OraDatabase や OraDynaset の
                  オブジェクト変数にnothing代入で
                  解放になるでしょうか?
                  ※今回の場合はOraDatabaseが対象でしょうか?

                  明示的にnothingを代入せずに
                  スレッドの終了時点で解放されるのを期待した場合
                  今回のような現象が発生するのでしょうか?

                  そもそも、今回の
                  oip10!DllUnregisterServer
                  はどのタイミングで実行される処理なのでしょうか?


                  ちなみに、
                  プログラム内で、明示的にnothingを代入していない箇所が
                  いくつかありました・・・
                  • 6. Re: OO4Oのスレッドセーフについて
                    830749
                    どこで問題が発生しているのかは明確になっているので、なぜ問題が発生したかを調査
                    したいのだろうと思っていたのですが。
                    850534 wrote:
                    Function Scope Line Of Code Source File Line Number
                    fncOpenDB Set objOradatabase = OraSession.GetDatabaseFromPool(10) 0
                    fncGetUserInfo Call fncOpenDB() 0
                    Global Scope Call fncGetUserInfo(strUSERCD, strUSERPASS, strUSERKUBUN, strZENSCD, strKENCD, strKENSCD, strJACD, strJASCD, strMCCD, strMCSCD, strNAME, strMAIL) 0
                    を見れば分かるように、fncGetUserInfoを実行しようとしたときにDatabaseをOpenしようと
                    した時点でOraSessionが解放されていたということになると思います。
                    OraSessionとOraDatabaseは親子関係にありますから、OraSessionを解放した後では
                    OraDatabaseはCreateできません。
                    OraSessionを含めて、各オブジェクトの解放手順を精査するのも良いと思います。

                    各オブジェクトは解放すべき時点でその親オブジェクトより先に解放する必要があります。
                    親子関係にあるオブジェクトはその解放順序を自分で制御しないと、先に親オブジェクトを
                    解放してしまうことがあります。マルチスレッドで親子のオブジェクトが複数のスレッドに
                    分かれている場合、そこにバグが入りやすいのかもしれません。

                    ちなみに、VBではCreateObjectしたオブジェクトはNothingで解放するものです。
                    • 7. Re: OO4Oのスレッドセーフについて
                      853537
                      ありがとうございます。

                      いろいろと調査したところ、
                      オラクルの内部障害だということがわかりました。

                      文書番号:124357

                      パッチをあてると良いようなので、
                      その方向で対応したいと思います。

                      色々とアドバイスいただき
                      本当にありがとうございました。