nao16t at gmail.com
2008-Jan-04 14:41 UTC
[Win32utils-devel] win32-api callback causes ruby to application error (crash).
# I originally intended to post this question here. # But it took some time for subscription authorization process. # So I have posted the same question to the forum when I was waiting # for the subscription confirmation notice. # It seems to me the forum is not so active, let me drop here too. Hello, The following WinSNMP trap receive program ''win_snmp.rb'' causes ruby interpreter to application error when the callback is invoked just after sending a trap by ''trapv2.rb''. This ruby program is written based on the WinSNMP C/C++ sample program at http://www.winsnmp.com/samples/c/cm_traps.c which works OK. So ''win_snmp.rb'' should be OK, I think. Would someone please give me some advice ? My environment: Windows XP Pro SP2 with MS SNMP Agent and Trap Service. ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32] win32-api (1.0.5) snmp (1.0.1) -----------start win_snmp.rb------------------- require ''win32/api'' include Win32 SnmpStartup = API.new(''SnmpStartup'', ''PPPPP'', ''L'', ''Wsnmp32'') SnmpGetLastError = API.new(''SnmpGetLastError'', ''L'', ''L'', ''Wsnmp32'') SnmpCreateSession = API.new(''SnmpCreateSession'', ''LLKP'', ''L'', ''Wsnmp32'') SnmpRegister = API.new(''SnmpRegister'', ''LLLLPL'', ''L'', ''Wsnmp32'') nMajorVersion = 0.chr * 4 MinorVersion = 0.chr * 4 nTranslateMode = 0.chr * 4 nRetransmitMode = 0.chr * 4 nLevel = 0.chr * 4 result = SnmpStartup.call(nMajorVersion, MinorVersion, nLevel, nTranslateMode, nRetransmitMode) puts "SnmpStartup: #{result}" printf("nMajorVersion: %s MinorVersion: %s nLevel: %s nTranslateMode: %s nRetransmitMode: %s\n", nMajorVersion.unpack("L*"), MinorVersion.unpack("L*"), nLevel.unpack ("L*"), nTranslateMode.unpack("L*"), nRetransmitMode.unpack("L*")) puts "SnmpGetLastError: #{SnmpGetLastError.call(nil)}" SNMPAPI_CALLBACK = API::Callback.new(''LLLLPP'', ''L''){ |hSession, hWnd, wMsg, wParam, lParam, lpClientData| puts "Trap Recieved!" } session = SnmpCreateSession.call(nil, 0, SNMPAPI_CALLBACK, nil) puts "SnmpCreateSession: #{session}" puts "SnmpGetLastError: #{SnmpGetLastError.call(session)}" SNMPAPI_ON = 1 result = SnmpRegister.call(session, nil, nil, nil, nil, SNMPAPI_ON) puts "SnmpRegister: #{result}" puts "SnmpGetLastError: #{SnmpGetLastError.call(session)}" sleep(60) -----------end win_snmp.rb------------------- Console output of the win_snmp.rb: ------------------------------------------------ SnmpStartup: 1 nMajorVersion: 2 MinorVersion: 0 nLevel: 2 nTranslateMode: 1 nRetransmitMode: 1 SnmpGetLastError: 1 SnmpCreateSession: 1 SnmpGetLastError: 1 SnmpRegister: 1 SnmpGetLastError: 1 ------------------------------------------------ The following code is to send a SNMP trap. -----------start trapv2.rb------------------- require ''rubygems'' require ''snmp'' SNMP::Manager.open(:TrapPort => 162, :Version => :SNMPv2c) do |snmp| 1.times { |i| p i snmp.trap_v2(12345, "1.3.6.1", ["1.3.6.1.2", "1.3.6.1.3"]) } end -----------end trapv2.rb------------------- Thanks. -nao -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/win32utils-devel/attachments/20080104/372abf41/attachment.html
Daniel Berger
2008-Jan-05 17:33 UTC
[Win32utils-devel] win32-api callback causes ruby to application error (crash).
Hi Nao, nao16t at gmail.com wrote:> # I originally intended to post this question here. > # But it took some time for subscription authorization process. > # So I have posted the same question to the forum when I was waiting > # for the subscription confirmation notice. > # It seems to me the forum is not so active, let me drop here too.That''s fine. I monitor both. <snip>> SNMPAPI_CALLBACK = API::Callback.new(''LLLLPP'', ''L''){ |hSession, hWnd, > wMsg, wParam, lParam, lpClientData| > puts "Trap Recieved!" > }I haven''t tested it, but shouldn''t the 5th parameter be ''L''. The docs say lParam is a 32 bit identifier. Regards, Dan
nao16t at gmail.com
2008-Jan-06 13:16 UTC
[Win32utils-devel] win32-api callback causes ruby to application error (crash).
Dan-san, Thank you for finding out my careless mistake. Now the callback turned to be invoked. But still Ruby interpreter crashes inside the callback. Basically does the win32 callback run under the ruby main thread ? Isn''t the win32 callback called by creating a new ruby thread ? If I call ruby "sleep()" at the bottom of code, the win32 callback is blocked until the ruby sleep returns. If I call win32 "Sleep()" at the bottom of code, ruby interpreter crushes inside the callback. How should the ruby mainthread wait for the asynchronous win32 callback ? I tried several work-arounds, but so far no luck. I commented out the lines what I did in the following code. Best regards, -nao require ''win32/api'' include Win32 SNMPAPI_FAILURE = 0 SNMPAPI_SUCCESS = 1 SnmpStartup = API.new(''SnmpStartup'', ''PPPPP'', ''L'', ''Wsnmp32'') SnmpGetLastError = API.new(''SnmpGetLastError'', ''L'', ''L'', ''Wsnmp32'') SnmpCreateSession = API.new(''SnmpCreateSession'', ''LLKP'', ''L'', ''Wsnmp32'') SnmpRegister = API.new(''SnmpRegister'', ''LLLLPL'', ''L'', ''Wsnmp32'') SnmpRecvMsg = API.new(''SnmpRecvMsg'', ''LPPPP'', ''L'', ''Wsnmp32'') SnmpGetPduData = API.new(''SnmpGetPduData'', ''LPPPPP'', ''L'', ''Wsnmp32'') SnmpFreeVbl = API.new(''SnmpFreeVbl'',''L'', ''L'', ''Wsnmp32'') SnmpFreePdu = API.new(''SnmpFreePdu'', ''L'', ''L'', ''Wsnmp32'') Sleep = API.new(''Sleep'', ''L'', ''V'') #th = Thread.new { nMajorVersion = 0.chr * 4 MinorVersion = 0.chr * 4 nTranslateMode = 0.chr * 4 nRetransmitMode = 0.chr * 4 nLevel = 0.chr * 4 result = SnmpStartup.call(nMajorVersion, MinorVersion, nLevel, nTranslateMode, nRetransmitMode) puts "SnmpStartup: #{result}" printf("nMajorVersion: %s MinorVersion: %s nLevel: %s nTranslateMode: %s nRetransmitMode: %s\n", nMajorVersion.unpack("L*"), MinorVersion.unpack("L*"), nLevel.unpack ("L*"), nTranslateMode.unpack("L*"), nRetransmitMode.unpack("L*")) puts "SnmpGetLastError: #{SnmpGetLastError.call(nil)}" SNMPAPI_CALLBACK = API::Callback.new(''LLLLLP'', ''L''){ |hSession, hWnd, wMsg, wParam, lParam, lpClientData| # Thread.new(hSession, hWnd, wMsg, wParam, lParam, lpClientData) {|hSession, hWnd, wMsg, wParam, lParam, lpClientData| hPdu = 0.chr * 4 lType = 0.chr * 4 lReqId = 0.chr * 4 lErr = 0.chr * 4 lIdx = 0.chr * 4 hVbl = 0.chr * 4 puts "Trap Recieved, start callback!" state = SnmpRecvMsg.call(hSession, nil, nil, nil, hPdu) puts "SnmpRecvMsg: #{state}" state = SnmpGetPduData.call(hPdu.pack("L*"), lType, lReqId, lErr, lIdx, hVbl) puts "SnmpGetPduData: #{state}" state = SnmpFreeVbl.call(hVbl.pack("L*")) puts "SnmpFreeVbl: #{state}" state = SnmpFreePdu.call(hPdu.pack("L*")) puts "SnmpFreePdu: #{state}" puts "Trap Recieved, end callback!" # } return(SNMPAPI_SUCCESS) } session = SnmpCreateSession.call(nil, 0, SNMPAPI_CALLBACK, nil) puts "SnmpCreateSession: #{session}" puts "SnmpGetLastError: #{SnmpGetLastError.call(session)}" SNMPAPI_ON = 1 result = SnmpRegister.call(session, nil, nil, nil, nil, SNMPAPI_ON) puts "SnmpRegister: #{result}" puts "SnmpGetLastError: #{SnmpGetLastError.call(session)}" #} #th.join #loop do # Thread.pass #end # Sleep.call(60000) #sleep(60) #60.times { # sleep(1) #} 2008/1/6, Daniel Berger <djberg96 at gmail.com>:> > Hi Nao, > > nao16t at gmail.com wrote: > > # I originally intended to post this question here. > > # But it took some time for subscription authorization process. > > # So I have posted the same question to the forum when I was waiting > > # for the subscription confirmation notice. > > # It seems to me the forum is not so active, let me drop here too. > > That''s fine. I monitor both. > > <snip> > > > SNMPAPI_CALLBACK = API::Callback.new(''LLLLPP'', ''L''){ |hSession, hWnd, > > wMsg, wParam, lParam, lpClientData| > > puts "Trap Recieved!" > > } > > I haven''t tested it, but shouldn''t the 5th parameter be ''L''. The docs > say lParam is a 32 bit identifier. > > Regards, > > Dan > _______________________________________________ > win32utils-devel mailing list > win32utils-devel at rubyforge.org > http://rubyforge.org/mailman/listinfo/win32utils-devel >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/win32utils-devel/attachments/20080106/946e3fbc/attachment.html
Daniel Berger
2008-Jan-06 13:41 UTC
[Win32utils-devel] win32-api callback causes ruby to application error (crash).
Hi, nao16t at gmail.com wrote:> Dan-san, > > Thank you for finding out my careless mistake. > Now the callback turned to be invoked. > > But still Ruby interpreter crashes inside the callback. > > Basically does the win32 callback run under the ruby main thread ? > Isn''t the win32 callback called by creating a new ruby thread ?It runs in Ruby''s main thread. Perhaps we should execute callbacks in their own Ruby thread. Does anyone else have any thoughts on this? It seems like a reasonable idea on the surface, but I may be missing deeper issues.> If I call ruby "sleep()" at the bottom of code, the win32 callback is > blocked until the ruby sleep returns. > > If I call win32 "Sleep()" at the bottom of code, ruby interpreter > crushes inside the callback. > > How should the ruby mainthread wait for the asynchronous win32 > callback ? > > I tried several work-arounds, but so far no luck. > I commented out the lines what I did in the following code.I''m on a business trip this week so I won''t have much time to play with it until next week I''m afraid. Perhaps someone else on the list can give this a try and see what the issue is. Regards, Dan
nao16t at gmail.com
2008-Jan-07 16:15 UTC
[Win32utils-devel] win32-api callback causes ruby to application error (crash).
Hello all, & Dan-san,> It runs in Ruby''s main thread.OK. Perhaps we should execute callbacks in> their own Ruby thread. Does anyone else have any thoughts on this? It > seems like a reasonable idea on the surface, but I may be missing deeper > issues.Ruby interpreter itself is single-threaded. But win32 callback is inherently multi-threaded. So I have no idea how win32-api C extension code should handle the win32 callback. In case of WinSNMP, is it better to write another C extension code somehow the win32 callback thread puts trap data into a queue, then ruby thread polls the queue ? Best regards, -nao -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/win32utils-devel/attachments/20080108/b96a1af4/attachment.html
Daniel Berger
2008-Jan-20 19:09 UTC
[Win32utils-devel] win32-api callback causes ruby to application error (crash).
nao16t at gmail.com wrote:> Hello all, & Dan-san, > > > It runs in Ruby''s main thread. > > > OK. > > Perhaps we should execute callbacks in > their own Ruby thread. Does anyone else have any thoughts on this? It > seems like a reasonable idea on the surface, but I may be missing deeper > issues. > > > Ruby interpreter itself is single-threaded. > But win32 callback is inherently multi-threaded. > So I have no idea how win32-api C extension code should handle the win32 > callback. > In case of WinSNMP, is it better to write another C extension code > somehow the win32 callback thread puts trap data into a queue, then ruby > thread polls the queue ?After today''s experiment with SetConsoleCtrlHandler() I''m not so sure this is possible to solve with Ruby 1.8.x. We may have hit a wall here. This is bad. If anyone has any ideas, please help! Thanks, Dan