diff options
author | Jose <jose@zeroc.com> | 2011-05-04 19:46:35 +0200 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2011-05-04 19:46:35 +0200 |
commit | d163d1324bb09a5dd00bb0b1cc784d6cb7cc1c25 (patch) | |
tree | bdb670583f5fee0ca095ab53a1faee4eff7047c0 | |
parent | RPM fixes for RHEL6 (diff) | |
download | ice-d163d1324bb09a5dd00bb0b1cc784d6cb7cc1c25.tar.bz2 ice-d163d1324bb09a5dd00bb0b1cc784d6cb7cc1c25.tar.xz ice-d163d1324bb09a5dd00bb0b1cc784d6cb7cc1c25.zip |
5053 - Glacier2 helper deadlock
26 files changed, 1481 insertions, 141 deletions
diff --git a/cs/allTests.py b/cs/allTests.py index 7d9816f8f02..c08f1b2be98 100755 --- a/cs/allTests.py +++ b/cs/allTests.py @@ -60,6 +60,7 @@ tests = [ ("Ice/invoke", ["core"]), ("IceBox/configuration", ["core", "noipv6"]), ("Glacier2/router", ["service"]), + ("Glacier2/sessionHelper", ["service"]), ("IceGrid/simple", ["service"]), ("IceSSL/configuration", ["once", "novista", "nomono"]), ] diff --git a/cs/src/Glacier2/SessionHelper.cs b/cs/src/Glacier2/SessionHelper.cs index b801cbcf2a1..b88de50c4b5 100644 --- a/cs/src/Glacier2/SessionHelper.cs +++ b/cs/src/Glacier2/SessionHelper.cs @@ -326,20 +326,28 @@ public class SessionHelper private void connected(RouterPrx router, SessionPrx session) { + string category = router.getCategoryForClient(); + long timeout = router.getSessionTimeout(); + Ice.Connection conn = router.ice_getCachedConnection(); lock(this) { _router = router; if(_destroy) { - destroyInternal(); + // + // Run the destroyInternal in a thread. This is because it + // destroyInternal makes remote invocations. + // + Thread t = new Thread(new ThreadStart(destroyInternal)); + t.Start(); return; } // // Cache the category. // - _category = _router.getCategoryForClient(); + _category = category; // // Assign the session after _destroy is checked. @@ -348,7 +356,7 @@ public class SessionHelper _connected = true; Debug.Assert(_sessionRefresh == null); - _sessionRefresh = new SessionRefreshThread(this, _router, (int)(_router.getSessionTimeout() * 1000)/2); + _sessionRefresh = new SessionRefreshThread(this, _router, (int)(timeout * 1000)/2); _refreshThread = new Thread(new ThreadStart(_sessionRefresh.run)); _refreshThread.Start(); @@ -363,76 +371,90 @@ public class SessionHelper { destroy(); } - }, _session.ice_getCachedConnection()); + }, conn); } } private void destroyInternal() { + Glacier2.RouterPrx router; + Ice.Communicator communicator; + SessionRefreshThread sessionRefresh; lock(this) { Debug.Assert(_destroy); - - try - { - _router.destroySession(); - } - catch(Ice.ConnectionLostException) - { - // - // Expected if another thread invoked on an object from the session concurrently. - // - } - catch(SessionNotExistException) - { - // - // This can also occur. - // - } - catch(Exception e) + if(_router == null) { - // - // Not expected. - // - _communicator.getLogger().warning("SessionHelper: unexpected exception when destroying the session:\n" - + e); + return; } + router = _router; _router = null; - _connected = false; - if(_sessionRefresh != null) + + communicator = _communicator; + _communicator = null; + + Debug.Assert(communicator != null); + + sessionRefresh = _sessionRefresh; + _sessionRefresh = null; + } + + try + { + router.destroySession(); + } + catch(Ice.ConnectionLostException) + { + // + // Expected if another thread invoked on an object from the session concurrently. + // + } + catch(SessionNotExistException) + { + // + // This can also occur. + // + } + catch(Exception e) + { + // + // Not expected. + // + communicator.getLogger().warning("SessionHelper: unexpected exception when destroying the session:\n" + e); + } + _connected = false; + if(sessionRefresh != null) + { + sessionRefresh.done(); + while(true) { - _sessionRefresh.done(); - while(true) + try + { + _refreshThread.Join(); + break; + } + catch(ThreadInterruptedException) { - try - { - _refreshThread.Join(); - break; - } - catch(ThreadInterruptedException) - { - } } - _sessionRefresh = null; - _refreshThread = null; } + _refreshThread = null; + } - try - { - _communicator.destroy(); - } - catch(Exception) - { - } - _communicator = null; - // Notify the callback that the session is gone. - dispatchCallback(delegate() - { - _callback.disconnected(this); - }, null); + try + { + communicator.destroy(); } + catch(Exception) + { + } + + // Notify the callback that the session is gone. + dispatchCallback(delegate() + { + _callback.disconnected(this); + }, null); } delegate Glacier2.SessionPrx ConnectStrategy(Glacier2.RouterPrx router); @@ -479,7 +501,7 @@ public class SessionHelper catch(Exception) { } - + _communicator = null; dispatchCallback(delegate() { _callback.connectFailed(this, ex); diff --git a/cs/test/Glacier2/Makefile b/cs/test/Glacier2/Makefile index 70cf2f19cb0..d6b91d91885 100644 --- a/cs/test/Glacier2/Makefile +++ b/cs/test/Glacier2/Makefile @@ -11,7 +11,7 @@ top_srcdir = ../.. include $(top_srcdir)/config/Make.rules.cs -SUBDIRS = router +SUBDIRS = router sessionHelper $(EVERYTHING):: @for subdir in $(SUBDIRS); \ diff --git a/cs/test/Glacier2/Makefile.mak b/cs/test/Glacier2/Makefile.mak index 9c984483478..c812ef3ad48 100644 --- a/cs/test/Glacier2/Makefile.mak +++ b/cs/test/Glacier2/Makefile.mak @@ -11,7 +11,7 @@ top_srcdir = ..\.. !include $(top_srcdir)\config\Make.rules.mak.cs
-SUBDIRS = router
+SUBDIRS = router sessionHelper
$(EVERYTHING)::
@for %i in ( $(SUBDIRS) ) do \
diff --git a/cs/test/Glacier2/sessionHelper/.depend b/cs/test/Glacier2/sessionHelper/.depend new file mode 100644 index 00000000000..9a9db739c3c --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/.depend @@ -0,0 +1 @@ +generated/Callback.cs: ./Callback.ice $(SLICE2CS) $(SLICEPARSERLIB) diff --git a/cs/test/Glacier2/sessionHelper/.depend.mak b/cs/test/Glacier2/sessionHelper/.depend.mak new file mode 100644 index 00000000000..70e49523d5c --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/.depend.mak @@ -0,0 +1 @@ +generated/Callback.cs: ./Callback.ice "$(SLICE2CS)" "$(SLICEPARSERLIB)" diff --git a/cs/test/Glacier2/sessionHelper/Callback.ice b/cs/test/Glacier2/sessionHelper/Callback.ice new file mode 100644 index 00000000000..38b591ed67c --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/Callback.ice @@ -0,0 +1,43 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef CALLBACK_ICE +#define CALLBACK_ICE + +[["java:package:test.Glacier2.sessionHelper"]] +module Test +{ + +exception CallbackException +{ + double someValue; + string someString; +}; + +interface CallbackReceiver +{ + void callback(); + + void callbackEx() + throws CallbackException; +}; + +interface Callback +{ + void initiateCallback(CallbackReceiver* proxy); + + void initiateCallbackEx(CallbackReceiver* proxy) + throws CallbackException; + + void shutdown(); +}; + +}; + +#endif diff --git a/cs/test/Glacier2/sessionHelper/CallbackI.cs b/cs/test/Glacier2/sessionHelper/CallbackI.cs new file mode 100644 index 00000000000..16d5d32e83b --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/CallbackI.cs @@ -0,0 +1,36 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +using Test; +using System.Diagnostics; + +public sealed class CallbackI : Test.CallbackDisp_ +{ + public CallbackI() + { + } + + public override void + initiateCallback(CallbackReceiverPrx proxy, Ice.Current current) + { + proxy.callback(current.ctx); + } + + public override void + initiateCallbackEx(CallbackReceiverPrx proxy, Ice.Current current) + { + proxy.callbackEx(current.ctx); + } + + public override void + shutdown(Ice.Current current) + { + current.adapter.getCommunicator().shutdown(); + } +} diff --git a/cs/test/Glacier2/sessionHelper/Client.cs b/cs/test/Glacier2/sessionHelper/Client.cs new file mode 100644 index 00000000000..11b4f747846 --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/Client.cs @@ -0,0 +1,424 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +using Glacier2; +using Test; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Threading; + +[assembly: CLSCompliant(true)] + +[assembly: AssemblyTitle("IceTest")] +[assembly: AssemblyDescription("Ice test")] +[assembly: AssemblyCompany("ZeroC, Inc.")] + +public class Client +{ + public class App : Ice.Application + { + public App() + { + me = this; + } + + public class SessionCalback1 : Glacier2.SessionCallback + { + public void + connected(Glacier2.SessionHelper session) + { + test(false); + } + + public void + disconnected(Glacier2.SessionHelper session) + { + test(false); + } + + public void + connectFailed(Glacier2.SessionHelper session, System.Exception exception) + { + try + { + throw exception; + } + catch(Glacier2.PermissionDeniedException) + { + Console.Out.WriteLine("ok"); + lock(me) + { + wakeUp(); + } + } + catch(System.Exception) + { + test(false); + } + } + + public void + createdCommunicator(Glacier2.SessionHelper session) + { + test(session.communicator() != null); + } + } + + public class SessionCalback2 : Glacier2.SessionCallback + { + public void + connected(Glacier2.SessionHelper session) + { + Console.Out.WriteLine("ok"); + lock(me) + { + wakeUp(); + } + } + + public void + disconnected(Glacier2.SessionHelper session) + { + Console.Out.WriteLine("ok"); + lock(me) + { + wakeUp(); + } + } + + public void + connectFailed(Glacier2.SessionHelper session, System.Exception ex) + { + Console.Out.WriteLine(ex.ToString()); + test(false); + } + + public void + createdCommunicator(Glacier2.SessionHelper session) + { + test(session.communicator() != null); + } + } + + public class SessionCalback3 : Glacier2.SessionCallback + { + public void + connected(Glacier2.SessionHelper session) + { + test(false); + } + + public void + disconnected(Glacier2.SessionHelper session) + { + test(false); + } + + public void + connectFailed(Glacier2.SessionHelper session, System.Exception exception) + { + try + { + throw exception; + } + catch(Ice.ConnectionRefusedException) + { + Console.Out.WriteLine("ok"); + lock(me) + { + wakeUp(); + } + } + catch(System.Exception) + { + test(false); + } + } + + public void + createdCommunicator(Glacier2.SessionHelper session) + { + test(session.communicator() != null); + } + } + + public override int run(string[] args) + { + Ice.InitializationData initData = new Ice.InitializationData(); + initData.properties = Ice.Util.createProperties(ref args); + initData.properties.setProperty("Ice.Default.Router", "Glacier2/router:default -p 12347"); + initData.dispatcher = delegate(System.Action action, Ice.Connection connection) + { + action(); + }; + + _factory = new Glacier2.SessionFactoryHelper(initData, new SessionCalback1()); + + // + // Test to create a session with wrong userid/password + // + lock(this) + { + Console.Out.Write("testing SessionHelper connect with wrong userid/password... "); + Console.Out.Flush(); + + _factory.setRouterHost("127.0.0.1"); + _factory.setPort(12347); + _factory.setRouterIdentity(Ice.Util.stringToIdentity("Glacier2/router")); + _factory.setSecure(false); + _session = _factory.connect("userid", "xxx"); + while(true) + { + try + { + System.Threading.Monitor.Wait(this); + break; + } + catch(ThreadInterruptedException) + { + } + } + } + + _factory = new Glacier2.SessionFactoryHelper(initData, new SessionCalback2()); + lock(this) + { + Console.Out.Write("testing SessionHelper connect... "); + Console.Out.Flush(); + _factory.setRouterHost("127.0.0.1"); + _factory.setPort(12347); + _factory.setRouterIdentity(Ice.Util.stringToIdentity("Glacier2/router")); + _factory.setSecure(false); + _session = _factory.connect("userid", "abc123"); + while(true) + { + try + { + System.Threading.Monitor.Wait(this); + break; + } + catch(ThreadInterruptedException) + { + } + } + + Console.Out.Write("testing SessionHelper isConnected after connect... "); + Console.Out.Flush(); + test(_session.isConnected()); + Console.Out.WriteLine("ok"); + + Console.Out.Write("testing SessionHelper categoryForClient after connect... "); + Console.Out.Flush(); + try + { + test(!_session.categoryForClient().Equals("")); + } + catch(Glacier2.SessionNotExistException) + { + test(false); + } + Console.Out.WriteLine("ok"); + + // try + // { + // test(_session.session() != null); + // } + // catch(Glacier2.SessionNotExistException ex) + // { + // test(false); + // } + + Console.Out.Write("testing stringToProxy for server object... "); + Console.Out.Flush(); + Ice.ObjectPrx @base = _session.communicator().stringToProxy("callback:tcp -p 12010"); + Console.Out.WriteLine("ok"); + + Console.Out.Write("pinging server after session creation... "); + Console.Out.Flush(); + @base.ice_ping(); + Console.Out.WriteLine("ok"); + + Console.Out.Write("testing checked cast for server object... "); + Console.Out.Flush(); + CallbackPrx twoway = CallbackPrxHelper.checkedCast(@base); + test(twoway != null); + Console.Out.WriteLine("ok"); + + Console.Out.Write("testing server shutdown... "); + Console.Out.Flush(); + twoway.shutdown(); + Console.Out.WriteLine("ok"); + + test(_session.communicator() != null); + Console.Out.Write("testing SessionHelper destroy... "); + Console.Out.Flush(); + _session.destroy(); + while(true) + { + try + { + System.Threading.Monitor.Wait(this); + break; + } + catch(ThreadInterruptedException) + { + } + } + + Console.Out.Write("testing SessionHelper isConnected after destroy... "); + Console.Out.Flush(); + test(_session.isConnected() == false); + Console.Out.WriteLine("ok"); + + Console.Out.Write("testing SessionHelper categoryForClient after destroy... "); + Console.Out.Flush(); + try + { + test(!_session.categoryForClient().Equals("")); + test(false); + } + catch(Glacier2.SessionNotExistException) + { + } + Console.Out.WriteLine("ok"); + + Console.Out.Write("testing SessionHelper session after destroy... "); + try + { + _session.session(); + test(false); + } + catch(Glacier2.SessionNotExistException) + { + } + Console.Out.WriteLine("ok"); + + Console.Out.Write("testing SessionHelper communicator after destroy... "); + Console.Out.Flush(); + test(_session.communicator() == null); + Console.Out.WriteLine("ok"); + + + Console.Out.Write("uninstalling router with communicator... "); + Console.Out.Flush(); + communicator().setDefaultRouter(null); + Console.Out.WriteLine("ok"); + + Ice.ObjectPrx processBase; + { + Console.Out.Write("testing stringToProxy for process object... "); + processBase = communicator().stringToProxy("Glacier2/admin -f Process:tcp -h 127.0.0.1 -p 12348"); + Console.Out.WriteLine("ok"); + } + + + Ice.ProcessPrx process; + { + Console.Out.Write("testing checked cast for admin object... "); + process = Ice.ProcessPrxHelper.checkedCast(processBase); + test(process != null); + Console.Out.WriteLine("ok"); + } + + Console.Out.Write("testing Glacier2 shutdown... "); + process.shutdown(); + try + { + process.ice_ping(); + test(false); + } + catch(Ice.LocalException) + { + Console.Out.WriteLine("ok"); + } + } + + _factory = new Glacier2.SessionFactoryHelper(initData, new SessionCalback3()); + lock(this) + { + Console.Out.Write("testing SessionHelper connect after router shutdown... "); + Console.Out.Flush(); + + _factory.setRouterHost("127.0.0.1"); + _factory.setPort(12347); + _factory.setRouterIdentity(Ice.Util.stringToIdentity("Glacier2/router")); + _factory.setSecure(false); + _session = _factory.connect("userid", "abc123"); + while(true) + { + try + { + System.Threading.Monitor.Wait(this); + break; + } + catch(ThreadInterruptedException) + { + } + } + + Console.Out.Write("testing SessionHelper isConnect after connect failure... "); + Console.Out.Flush(); + test(_session.isConnected() == false); + Console.Out.WriteLine("ok"); + + Console.Out.Write("testing SessionHelper communicator after connect failure... "); + Console.Out.Flush(); + test(_session.communicator() == null); + Console.Out.WriteLine("ok"); + + Console.Out.Write("testing SessionHelper destroy after connect failure... "); + Console.Out.Flush(); + _session.destroy(); + Console.Out.WriteLine("ok"); + } + + return 0; + } + + public static void + wakeUp() + { + System.Threading.Monitor.Pulse(me); + } + + private static void + test(bool b) + { + if(!b) + { + throw new Exception(); + } + } + + public static App me; + private Glacier2.SessionHelper _session; + private Glacier2.SessionFactoryHelper _factory; + } + + public static void Main(string[] args) + { + Debug.Listeners.Add(new ConsoleTraceListener()); + Ice.InitializationData initData = new Ice.InitializationData(); + initData.properties = Ice.Util.createProperties(ref args); + + initData.properties.setProperty("Ice.Warn.Connections", "0"); + + App app = new App(); + int status = app.main(args, initData); + + if(status != 0) + { + Environment.Exit(status); + } + } + + +} diff --git a/cs/test/Glacier2/sessionHelper/Makefile b/cs/test/Glacier2/sessionHelper/Makefile new file mode 100644 index 00000000000..0c9f25a229a --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/Makefile @@ -0,0 +1,35 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +TARGETS = client.exe server.exe + +C_SRCS = Client.cs generated/Callback.cs CallbackI.cs +S_SRCS = Server.cs generated/Callback.cs CallbackI.cs + +SLICE_SRCS = $(SDIR)/Callback.ice + +SDIR = . + +GDIR = generated + +include $(top_srcdir)/config/Make.rules.cs + +MCSFLAGS := $(MCSFLAGS) -target:exe + +SLICE2CSFLAGS := $(SLICE2CSFLAGS) --ice -I. -I$(slicedir) + +client.exe: $(C_SRCS) $(GEN_SRCS) + $(MCS) $(MCSFLAGS) -out:$@ $(call ref,Ice) $(call ref,Glacier2) $(subst /,$(DSEP),$^) + +server.exe: $(S_SRCS) $(GEN_SRCS) + $(MCS) $(MCSFLAGS) -out:$@ $(call ref,Ice) $(call ref,Glacier2) $(subst /,$(DSEP),$^) + +include .depend diff --git a/cs/test/Glacier2/sessionHelper/Makefile.mak b/cs/test/Glacier2/sessionHelper/Makefile.mak new file mode 100644 index 00000000000..ff832a5883b --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/Makefile.mak @@ -0,0 +1,33 @@ +# **********************************************************************
+#
+# Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+top_srcdir = ..\..\..
+
+TARGETS = client.exe server.exe
+
+C_SRCS = Client.cs CallbackI.cs
+S_SRCS = Server.cs CallbackI.cs
+
+GEN_SRCS = $(GDIR)\Callback.cs
+
+SDIR = .
+
+GDIR = generated
+
+!include $(top_srcdir)\config\Make.rules.mak.cs
+
+MCSFLAGS = $(MCSFLAGS) -target:exe
+
+client.exe: $(C_SRCS) $(GEN_SRCS)
+ $(MCS) $(MCSFLAGS) -out:$@ -r:"$(refdir)\Ice.dll" -r:"$(refdir)\Glacier2.dll" $(C_SRCS) $(GEN_SRCS)
+
+server.exe: $(S_SRCS) $(GEN_SRCS)
+ $(MCS) $(MCSFLAGS) -out:$@ -r:"$(refdir)\Ice.dll" -r:"$(refdir)\Glacier2.dll" $(S_SRCS) $(GEN_SRCS)
+
+!include .depend.mak
diff --git a/cs/test/Glacier2/sessionHelper/Server.cs b/cs/test/Glacier2/sessionHelper/Server.cs new file mode 100644 index 00000000000..aa5828fd179 --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/Server.cs @@ -0,0 +1,47 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +using System; +using System.Diagnostics; +using System.Reflection; + +[assembly: CLSCompliant(true)] + +[assembly: AssemblyTitle("IceTest")] +[assembly: AssemblyDescription("Ice test")] +[assembly: AssemblyCompany("ZeroC, Inc.")] + +public class Server +{ + public class App : Ice.Application + { + public override int run(string[] args) + { + communicator().getProperties().setProperty("CallbackAdapter.Endpoints", "tcp -p 12010"); + Ice.ObjectAdapter adapter = communicator().createObjectAdapter("CallbackAdapter"); + adapter.add(new CallbackI(), + communicator().stringToIdentity("callback")); + adapter.activate(); + communicator().waitForShutdown(); + return 0; + } + } + + public static void Main(string[] args) + { + Debug.Listeners.Add(new ConsoleTraceListener()); + + App app = new App(); + int status = app.main(args); + if(status != 0) + { + Environment.Exit(status); + } + } +} diff --git a/cs/test/Glacier2/sessionHelper/client.exe.config b/cs/test/Glacier2/sessionHelper/client.exe.config new file mode 100755 index 00000000000..cf795ac3756 --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/client.exe.config @@ -0,0 +1,6 @@ +<?xml version="1.0"?>
+<configuration>
+ <runtime>
+ <developmentMode developerInstallation="true"/>
+ </runtime>
+</configuration>
diff --git a/cs/test/Glacier2/sessionHelper/generated/.gitignore b/cs/test/Glacier2/sessionHelper/generated/.gitignore new file mode 100644 index 00000000000..39af5887579 --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/generated/.gitignore @@ -0,0 +1 @@ +# Dummy file, so that git retains this otherwise empty directory. diff --git a/cs/test/Glacier2/sessionHelper/passwords b/cs/test/Glacier2/sessionHelper/passwords new file mode 100644 index 00000000000..a1527dec2b9 --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/passwords @@ -0,0 +1 @@ +userid xxMqsnnDcK8tw
\ No newline at end of file diff --git a/cs/test/Glacier2/sessionHelper/run.py b/cs/test/Glacier2/sessionHelper/run.py new file mode 100755 index 00000000000..37c77de8169 --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/run.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise "can't find toplevel directory!" +sys.path.append(os.path.join(path[0])) +from scripts import * + +router = os.path.join(TestUtil.getCppBinDir(), "glacier2router") + +args = ' --Ice.Warn.Dispatch=0' + \ + ' --Ice.Warn.Connections=0' + \ + ' --Glacier2.SessionTimeout="30"' + \ + ' --Glacier2.Client.Endpoints="default -p 12347"' + \ + ' --Glacier2.Server.Endpoints="tcp -h 127.0.0.1"' \ + ' --Ice.Admin.Endpoints="tcp -h 127.0.0.1 -p 12348"' + \ + ' --Ice.Admin.InstanceName=Glacier2' + \ + ' --Glacier2.CryptPasswords="' + os.path.join(os.getcwd(), "passwords") + '"' + +print "starting router...", +routerConfig = TestUtil.DriverConfig("server") +routerConfig.lang = "cpp" +starterProc = TestUtil.startServer(router, args, count=2, config=routerConfig) +print "ok" + + + +TestUtil.clientServerTest(additionalClientOptions=" --shutdown") + +starterProc.waitTestSuccess() + diff --git a/cs/test/Glacier2/sessionHelper/server.exe.config b/cs/test/Glacier2/sessionHelper/server.exe.config new file mode 100755 index 00000000000..cf795ac3756 --- /dev/null +++ b/cs/test/Glacier2/sessionHelper/server.exe.config @@ -0,0 +1,6 @@ +<?xml version="1.0"?>
+<configuration>
+ <runtime>
+ <developmentMode developerInstallation="true"/>
+ </runtime>
+</configuration>
diff --git a/java/allTests.py b/java/allTests.py index df988e7565f..4aa445a64cd 100755 --- a/java/allTests.py +++ b/java/allTests.py @@ -69,6 +69,7 @@ tests = [ ("Freeze/evictor", ["core"]), ("Freeze/fileLock", ["once"]), ("Glacier2/router", ["service"]), + ("Glacier2/sessionHelper", ["service"]), ("IceGrid/simple", ["service"]), ("IceSSL/configuration", ["once"]) ] diff --git a/java/build.xml b/java/build.xml index 004e4c757e4..3b856c78802 100644 --- a/java/build.xml +++ b/java/build.xml @@ -349,6 +349,9 @@ <fileset dir="test/Glacier2/router/"> <include name="Callback.ice" /> </fileset> + <fileset dir="test/Glacier2/sessionHelper/"> + <include name="Callback.ice" /> + </fileset> <fileset dir="test/IceGrid/simple/"> <include name="Test.ice" /> </fileset> diff --git a/java/src/Glacier2/SessionHelper.java b/java/src/Glacier2/SessionHelper.java index 25e788c8b09..9e1feab644c 100644 --- a/java/src/Glacier2/SessionHelper.java +++ b/java/src/Glacier2/SessionHelper.java @@ -108,37 +108,40 @@ public class SessionHelper * Once the session has been destroyed, {@link SessionCallback.disconnected} is called on * the associated callback object. */ - synchronized public void + public void destroy() { - if(_destroy) + synchronized(this) { - return; - } - _destroy = true; - if(_refreshThread == null) - { - // - // In this case a connecting session is being - // destroyed. The communicator and session will be - // destroyed when the connection establishment has - // completed. - // - return; - } - _session = null; + if(_destroy) + { + return; + } + _destroy = true; + if(_refreshThread == null) + { + // + // In this case a connecting session is being + // destroyed. The communicator and session will be + // destroyed when the connection establishment has + // completed. + // + return; + } + _session = null; - try - { - Runtime.getRuntime().removeShutdownHook(_shutdownHook); - } - catch(IllegalStateException ex) - { - // Ignore - } - catch(SecurityException ex) - { - // Ignore + try + { + Runtime.getRuntime().removeShutdownHook(_shutdownHook); + } + catch(IllegalStateException ex) + { + // Ignore + } + catch(SecurityException ex) + { + // Ignore + } } // @@ -311,81 +314,119 @@ public class SessionHelper }); } - synchronized private void + private void connected(RouterPrx router, SessionPrx session) { - _router = router; + Ice.Connection conn = router.ice_getCachedConnection(); + long timeout = router.getSessionTimeout(); + String category = router.getCategoryForClient(); - if(_destroy) + synchronized(this) { - destroyInternal(); - return; - } - - // - // Cache the category. - // - _category = _router.getCategoryForClient(); - - // - // Assign the session after _destroy is checked. - // - _session = session; - _connected = true; - - assert _refreshThread == null; - _refreshThread = new SessionRefreshThread(_router, (_router.getSessionTimeout() * 1000)/2); - _refreshThread.start(); + _router = router; - _shutdownHook = new Thread("Shutdown hook") - { - public void run() + if(_destroy) { - SessionHelper.this.destroy(); + // + // Run the destroyInternal in a thread. This is because it + // destroyInternal makes remote invocations. + // + new Thread(new Runnable() + { + public void run() + { + destroyInternal(); + } + }).start(); + return; } - }; - try - { - Runtime.getRuntime().addShutdownHook(_shutdownHook); - } - catch(IllegalStateException e) - { // - // Shutdown in progress, ignored + // Cache the category. // - } - catch(SecurityException ex) - { + _category = category; + // - // Ignore. Unsigned applets cannot registered shutdown hooks. + // Assign the session after _destroy is checked. // - } + _session = session; + _connected = true; - dispatchCallback(new Runnable() - { - public void run() + assert _refreshThread == null; + _refreshThread = new SessionRefreshThread(_router, (timeout * 1000)/2); + _refreshThread.start(); + + _shutdownHook = new Thread("Shutdown hook") { - try - { - _callback.connected(SessionHelper.this); - } - catch(SessionNotExistException ex) + public void run() { SessionHelper.this.destroy(); } + }; + + try + { + Runtime.getRuntime().addShutdownHook(_shutdownHook); + } + catch(IllegalStateException e) + { + // + // Shutdown in progress, ignored + // + } + catch(SecurityException ex) + { + // + // Ignore. Unsigned applets cannot registered shutdown hooks. + // } - }, _session.ice_getCachedConnection()); + } + + dispatchCallback(new Runnable() + { + public void run() + { + try + { + _callback.connected(SessionHelper.this); + } + catch(SessionNotExistException ex) + { + SessionHelper.this.destroy(); + } + } + }, conn); } - synchronized private void + private void destroyInternal() { assert _destroy; + Glacier2.RouterPrx router = null; + Ice.Communicator communicator = null; + SessionRefreshThread refreshThread = null; + synchronized(this) + { + if(_router == null) + { + return; + } + + router = _router; + _router = null; + + refreshThread = _refreshThread; + _refreshThread = null; + + communicator = _communicator; + _communicator = null; + } + + assert communicator != null; try { - _router.destroySession(); + router.destroySession(); } catch(Ice.ConnectionLostException e) { @@ -404,36 +445,33 @@ public class SessionHelper // // Not expected. // - _communicator.getLogger().warning("SessionHelper: unexpected exception when destroying the session:\n" + e); + communicator.getLogger().warning("SessionHelper: unexpected exception when destroying the session:\n" + e); } - _router = null; _connected = false; - if(_refreshThread != null) + if(refreshThread != null) { - _refreshThread.done(); + refreshThread.done(); while(true) { try { - _refreshThread.join(); + refreshThread.join(); break; } catch(InterruptedException e) { } } - _refreshThread = null; } try { - _communicator.destroy(); + communicator.destroy(); } catch(Throwable ex) { } - _communicator = null; // // Notify the callback that the session is gone. @@ -493,6 +531,7 @@ public class SessionHelper try { _communicator.destroy(); + _communicator = null; } catch(Throwable ex1) { diff --git a/java/test/Glacier2/sessionHelper/Callback.ice b/java/test/Glacier2/sessionHelper/Callback.ice new file mode 100644 index 00000000000..38b591ed67c --- /dev/null +++ b/java/test/Glacier2/sessionHelper/Callback.ice @@ -0,0 +1,43 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef CALLBACK_ICE +#define CALLBACK_ICE + +[["java:package:test.Glacier2.sessionHelper"]] +module Test +{ + +exception CallbackException +{ + double someValue; + string someString; +}; + +interface CallbackReceiver +{ + void callback(); + + void callbackEx() + throws CallbackException; +}; + +interface Callback +{ + void initiateCallback(CallbackReceiver* proxy); + + void initiateCallbackEx(CallbackReceiver* proxy) + throws CallbackException; + + void shutdown(); +}; + +}; + +#endif diff --git a/java/test/Glacier2/sessionHelper/CallbackI.java b/java/test/Glacier2/sessionHelper/CallbackI.java new file mode 100644 index 00000000000..8ad5c72d052 --- /dev/null +++ b/java/test/Glacier2/sessionHelper/CallbackI.java @@ -0,0 +1,40 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package test.Glacier2.sessionHelper; + +import test.Glacier2.sessionHelper.Test.CallbackException; +import test.Glacier2.sessionHelper.Test.CallbackReceiverPrx; +import test.Glacier2.sessionHelper.Test._CallbackDisp; + +final class CallbackI extends _CallbackDisp +{ + CallbackI() + { + } + + public void + initiateCallback(CallbackReceiverPrx proxy, Ice.Current current) + { + proxy.callback(current.ctx); + } + + public void + initiateCallbackEx(CallbackReceiverPrx proxy, Ice.Current current) + throws CallbackException + { + proxy.callbackEx(current.ctx); + } + + public void + shutdown(Ice.Current current) + { + current.adapter.getCommunicator().shutdown(); + } +} diff --git a/java/test/Glacier2/sessionHelper/Client.java b/java/test/Glacier2/sessionHelper/Client.java new file mode 100644 index 00000000000..f0ebe58f2c6 --- /dev/null +++ b/java/test/Glacier2/sessionHelper/Client.java @@ -0,0 +1,422 @@ + +package test.Glacier2.sessionHelper; + +import javax.swing.SwingUtilities; +import java.io.PrintWriter; +import java.io.StringWriter; + +import test.Glacier2.sessionHelper.Test.CallbackException; +import test.Glacier2.sessionHelper.Test.CallbackPrx; +import test.Glacier2.sessionHelper.Test.CallbackPrxHelper; +import test.Glacier2.sessionHelper.Test.CallbackReceiverPrx; +import test.Glacier2.sessionHelper.Test.CallbackReceiverPrxHelper; + +public class Client extends test.Util.Application +{ + Client() + { + out = getWriter(); + me = this; + } + + private static void + test(boolean b) + { + if(!b) + { + throw new RuntimeException(); + } + } + + public int run(String[] args) + { + Ice.InitializationData initData = new Ice.InitializationData(); + initData.properties = Ice.Util.createProperties(args); + initData.properties.setProperty("Ice.Default.Router", "Glacier2/router:default -p 12347"); + + initData.dispatcher = new Ice.Dispatcher() + { + public void + dispatch(Runnable runnable, Ice.Connection connection) + { + SwingUtilities.invokeLater(runnable); + } + }; + + _factory = new Glacier2.SessionFactoryHelper(initData, new Glacier2.SessionCallback() + { + public void + connected(Glacier2.SessionHelper session) + throws Glacier2.SessionNotExistException + { + test(false); + } + + public void + disconnected(Glacier2.SessionHelper session) + { + test(false); + } + + public void + connectFailed(Glacier2.SessionHelper session, Throwable exception) + { + try + { + throw exception; + } + catch(Glacier2.PermissionDeniedException ex) + { + out.println("ok"); + synchronized(test.Glacier2.sessionHelper.Client.this) + { + test.Glacier2.sessionHelper.Client.wakeUp(); + } + } + catch(Throwable ex) + { + test(false); + } + } + + public void + createdCommunicator(Glacier2.SessionHelper session) + { + test(session.communicator() != null); + } + }); + + // + // Test to create a session with wrong userid/password + // + synchronized(this) + { + out.print("testing SessionHelper connect with wrong userid/password... "); + out.flush(); + + _factory.setRouterHost("127.0.0.1"); + _factory.setPort(12347); + _factory.setRouterIdentity(Ice.Util.stringToIdentity("Glacier2/router")); + _factory.setSecure(false); + _session = _factory.connect("userid", "xxx"); + while(true) + { + try + { + wait(); + break; + } + catch(java.lang.InterruptedException ex) + { + } + } + } + + _factory = new Glacier2.SessionFactoryHelper(initData, new Glacier2.SessionCallback() + { + public void + connected(Glacier2.SessionHelper session) + throws Glacier2.SessionNotExistException + { + out.println("ok"); + synchronized(test.Glacier2.sessionHelper.Client.this) + { + test.Glacier2.sessionHelper.Client.wakeUp(); + } + } + + public void + disconnected(Glacier2.SessionHelper session) + { + out.println("ok"); + synchronized(test.Glacier2.sessionHelper.Client.this) + { + test.Glacier2.sessionHelper.Client.wakeUp(); + } + } + + public void + connectFailed(Glacier2.SessionHelper session, Throwable ex) + { + test(false); + } + + public void + createdCommunicator(Glacier2.SessionHelper session) + { + test(session.communicator() != null); + } + }); + + synchronized(this) + { + out.print("testing SessionHelper connect... "); + out.flush(); + _factory.setRouterHost("127.0.0.1"); + _factory.setPort(12347); + _factory.setRouterIdentity(Ice.Util.stringToIdentity("Glacier2/router")); + _factory.setSecure(false); + _session = _factory.connect("userid", "abc123"); + while(true) + { + try + { + wait(); + break; + } + catch(java.lang.InterruptedException ex) + { + } + } + + out.print("testing SessionHelper isConnected after connect... "); + out.flush(); + test(_session.isConnected()); + out.println("ok"); + + out.print("testing SessionHelper categoryForClient after connect... "); + out.flush(); + try + { + test(!_session.categoryForClient().equals("")); + } + catch(Glacier2.SessionNotExistException ex) + { + test(false); + } + out.println("ok"); + +// try +// { +// test(_session.session() != null); +// } +// catch(Glacier2.SessionNotExistException ex) +// { +// test(false); +// } + + out.print("testing stringToProxy for server object... "); + out.flush(); + Ice.ObjectPrx base = _session.communicator().stringToProxy("callback:tcp -p 12010"); + out.println("ok"); + + out.print("pinging server after session creation... "); + out.flush(); + base.ice_ping(); + out.println("ok"); + + out.print("testing checked cast for server object... "); + out.flush(); + CallbackPrx twoway = CallbackPrxHelper.checkedCast(base); + test(twoway != null); + out.println("ok"); + + out.print("testing server shutdown... "); + out.flush(); + twoway.shutdown(); + out.println("ok"); + + test(_session.communicator() != null); + out.print("testing SessionHelper destroy... "); + out.flush(); + _session.destroy(); + while(true) + { + try + { + wait(); + break; + } + catch(java.lang.InterruptedException ex) + { + } + } + + out.print("testing SessionHelper isConnected after destroy... "); + out.flush(); + test(_session.isConnected() == false); + out.println("ok"); + + out.print("testing SessionHelper categoryForClient after destroy... "); + out.flush(); + try + { + test(!_session.categoryForClient().equals("")); + test(false); + } + catch(Glacier2.SessionNotExistException ex) + { + } + out.println("ok"); + + out.print("testing SessionHelper session after destroy... "); + try + { + Glacier2.SessionPrx session = _session.session(); + test(false); + } + catch(Glacier2.SessionNotExistException ex) + { + } + out.println("ok"); + + out.print("testing SessionHelper communicator after destroy... "); + out.flush(); + test(_session.communicator() == null); + out.println("ok"); + + + out.print("uninstalling router with communicator... "); + out.flush(); + communicator().setDefaultRouter(null); + out.println("ok"); + + Ice.ObjectPrx processBase; + { + out.print("testing stringToProxy for process object... "); + processBase = communicator().stringToProxy("Glacier2/admin -f Process:tcp -h 127.0.0.1 -p 12348"); + out.println("ok"); + } + + + Ice.ProcessPrx process; + { + out.print("testing checked cast for admin object... "); + process = Ice.ProcessPrxHelper.checkedCast(processBase); + test(process != null); + out.println("ok"); + } + + out.print("testing Glacier2 shutdown... "); + process.shutdown(); + try + { + process.ice_ping(); + test(false); + } + catch(Ice.LocalException ex) + { + out.println("ok"); + } + } + + _factory = new Glacier2.SessionFactoryHelper(initData, new Glacier2.SessionCallback() + { + public void + connected(Glacier2.SessionHelper session) + throws Glacier2.SessionNotExistException + { + test(false); + } + + public void + disconnected(Glacier2.SessionHelper session) + { + test(false); + } + + public void + connectFailed(Glacier2.SessionHelper session, Throwable exception) + { + try + { + throw exception; + } + catch(Ice.ConnectionRefusedException ex) + { + out.println("ok"); + synchronized(test.Glacier2.sessionHelper.Client.this) + { + test.Glacier2.sessionHelper.Client.wakeUp(); + } + } + catch(Throwable ex) + { + test(false); + } + } + + public void + createdCommunicator(Glacier2.SessionHelper session) + { + test(session.communicator() != null); + } + }); + + // + // Wait a bit to ensure glaci2router has been shutdown. + // + while(true) + { + try + { + Thread.sleep(100); + break; + } + catch(java.lang.InterruptedException ex) + { + } + } + + synchronized(this) + { + out.print("testing SessionHelper connect after router shutdown... "); + out.flush(); + + _factory.setRouterHost("127.0.0.1"); + _factory.setPort(12347); + _factory.setRouterIdentity(Ice.Util.stringToIdentity("Glacier2/router")); + _factory.setSecure(false); + _session = _factory.connect("userid", "abc123"); + while(true) + { + try + { + wait(); + break; + } + catch(java.lang.InterruptedException ex) + { + } + } + + out.print("testing SessionHelper isConnect after connect failure... "); + out.flush(); + test(_session.isConnected() == false); + out.println("ok"); + + out.print("testing SessionHelper communicator after connect failure... "); + out.flush(); + test(_session.communicator() == null); + out.println("ok"); + + out.print("testing SessionHelper destroy after connect failure... "); + out.flush(); + _session.destroy(); + out.println("ok"); + } + + return 0; + } + + public static void + wakeUp() + { + me.notify(); + } + + public static void + main(String[] args) + { + Client c = new Client(); + int status = c.main("Client", args); + + System.gc(); + System.exit(status); + } + + private Glacier2.SessionHelper _session; + private Glacier2.SessionFactoryHelper _factory; + static public Client me; + final public PrintWriter out; +} diff --git a/java/test/Glacier2/sessionHelper/Server.java b/java/test/Glacier2/sessionHelper/Server.java new file mode 100644 index 00000000000..ae9838f3523 --- /dev/null +++ b/java/test/Glacier2/sessionHelper/Server.java @@ -0,0 +1,44 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package test.Glacier2.sessionHelper; + +public class Server extends test.Util.Application +{ + public int + run(String[] args) + { + communicator().getProperties().setProperty("CallbackAdapter.Endpoints", "tcp -p 12010"); + Ice.ObjectAdapter adapter = communicator().createObjectAdapter("CallbackAdapter"); + adapter.add(new CallbackI(), communicator().stringToIdentity("callback")); + adapter.activate(); + communicator().waitForShutdown(); + return 0; + } + + + protected Ice.InitializationData getInitData(Ice.StringSeqHolder argsH) + { + Ice.InitializationData initData = new Ice.InitializationData(); + initData.properties = Ice.Util.createProperties(argsH); + initData.properties.setProperty("Ice.Package.Test", "test.Glacier2.router"); + + return initData; + } + + public static void + main(String[] args) + { + Server c = new Server(); + int status = c.main("Server", args); + + System.gc(); + System.exit(status); + } +} diff --git a/java/test/Glacier2/sessionHelper/passwords b/java/test/Glacier2/sessionHelper/passwords new file mode 100644 index 00000000000..a1527dec2b9 --- /dev/null +++ b/java/test/Glacier2/sessionHelper/passwords @@ -0,0 +1 @@ +userid xxMqsnnDcK8tw
\ No newline at end of file diff --git a/java/test/Glacier2/sessionHelper/run.py b/java/test/Glacier2/sessionHelper/run.py new file mode 100755 index 00000000000..37c77de8169 --- /dev/null +++ b/java/test/Glacier2/sessionHelper/run.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise "can't find toplevel directory!" +sys.path.append(os.path.join(path[0])) +from scripts import * + +router = os.path.join(TestUtil.getCppBinDir(), "glacier2router") + +args = ' --Ice.Warn.Dispatch=0' + \ + ' --Ice.Warn.Connections=0' + \ + ' --Glacier2.SessionTimeout="30"' + \ + ' --Glacier2.Client.Endpoints="default -p 12347"' + \ + ' --Glacier2.Server.Endpoints="tcp -h 127.0.0.1"' \ + ' --Ice.Admin.Endpoints="tcp -h 127.0.0.1 -p 12348"' + \ + ' --Ice.Admin.InstanceName=Glacier2' + \ + ' --Glacier2.CryptPasswords="' + os.path.join(os.getcwd(), "passwords") + '"' + +print "starting router...", +routerConfig = TestUtil.DriverConfig("server") +routerConfig.lang = "cpp" +starterProc = TestUtil.startServer(router, args, count=2, config=routerConfig) +print "ok" + + + +TestUtil.clientServerTest(additionalClientOptions=" --shutdown") + +starterProc.waitTestSuccess() + |