aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamian Minkov <damencho@jitsi.org>2012-10-05 12:31:11 +0000
committerDamian Minkov <damencho@jitsi.org>2012-10-05 12:31:11 +0000
commit21c7757e23a6f4ae2daa42b74e53e1f693c9aa0e (patch)
treef7b7ec24b6327181fda096b104ffd49ca88fe528
parent19d2276dd4ff5e3458b9aafd876aa38391feeac5 (diff)
downloadjitsi-21c7757e23a6f4ae2daa42b74e53e1f693c9aa0e.zip
jitsi-21c7757e23a6f4ae2daa42b74e53e1f693c9aa0e.tar.gz
jitsi-21c7757e23a6f4ae2daa42b74e53e1f693c9aa0e.tar.bz2
Updates sysactivity handling QUERY_ENDSESSION and ENDSESSION events. Adds bundle that listens for the new events to handle clean shutdown.
-rw-r--r--lib/native/windows-64/sysactivitynotifications.dllbin56320 -> 58880 bytes
-rw-r--r--lib/native/windows/sysactivitynotifications.dllbin48640 -> 50688 bytes
-rw-r--r--resources/install/build.xml6
-rw-r--r--src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.cpp12
-rw-r--r--src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.h5
-rw-r--r--src/net/java/sip/communicator/impl/shutdowntimeout/ShutdownTimeout.java34
-rw-r--r--src/net/java/sip/communicator/impl/sysactivity/SystemActivityEventDispatcher.java19
-rw-r--r--src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java12
-rw-r--r--src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java24
-rw-r--r--src/net/java/sip/communicator/plugin/windowscleanshutdown/CleanShutdownActivator.java224
-rw-r--r--src/net/java/sip/communicator/plugin/windowscleanshutdown/cleanshutdown.manifest.mf12
-rw-r--r--src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java13
12 files changed, 356 insertions, 5 deletions
diff --git a/lib/native/windows-64/sysactivitynotifications.dll b/lib/native/windows-64/sysactivitynotifications.dll
index 1a301e6..160c21b 100644
--- a/lib/native/windows-64/sysactivitynotifications.dll
+++ b/lib/native/windows-64/sysactivitynotifications.dll
Binary files differ
diff --git a/lib/native/windows/sysactivitynotifications.dll b/lib/native/windows/sysactivitynotifications.dll
index be23766..64a526e 100644
--- a/lib/native/windows/sysactivitynotifications.dll
+++ b/lib/native/windows/sysactivitynotifications.dll
Binary files differ
diff --git a/resources/install/build.xml b/resources/install/build.xml
index 6c2eafa..71b7820 100644
--- a/resources/install/build.xml
+++ b/resources/install/build.xml
@@ -439,6 +439,12 @@
<include name="logging.properties" />
</fileset>
</copy>
+
+ <!-- Add the windows specific bundle path in the felix.client.run.properties file -->
+ <echo file="${light.dir}/lib/felix.client.run.properties"
+ append="true">felix.auto.start.14= reference:file:sc-bundles/windows-clean-shutdown.jar
+ </echo>
+
<mkdir dir="${light.dir}/lib/bundle" />
<copy todir="${light.dir}/lib/bundle" overwrite="true">
<fileset dir="${sc.basedir}/lib/bundle">
diff --git a/src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.cpp b/src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.cpp
index 67658e6..e4a2b80 100644
--- a/src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.cpp
+++ b/src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.cpp
@@ -396,6 +396,18 @@ HRESULT callback(UINT Msg, WPARAM wParam, LPARAM lParam)
return TRUE;
}
}
+ else if (Msg == WM_QUERYENDSESSION)
+ {
+ notify(net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_QUERY_ENDSESSION);
+ return TRUE;
+ }
+ else if (Msg == WM_ENDSESSION && wParam == TRUE)
+ {
+ // we fire the message only if we are really ending the session
+ // is wParam is False means someone has canceled the shutdown/logoff
+ notify(net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_ENDSESSION);
+ return TRUE;
+ }
jvm->DetachCurrentThread();
diff --git a/src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.h b/src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.h
index 885035e..7c5d55a 100644
--- a/src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.h
+++ b/src/native/sysactivity/net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications.h
@@ -29,7 +29,10 @@ extern "C" {
#define net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_NETWORK_CHANGE 9L
#undef net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_DNS_CHANGE
#define net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_DNS_CHANGE 10L
-
+#undef net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_QUERY_ENDSESSION
+#define net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_QUERY_ENDSESSION 11L
+#undef net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_ENDSESSION
+#define net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications_NOTIFY_ENDSESSION 12L
/*
* Class: net_java_sip_communicator_impl_sysactivity_SystemActivityNotifications
* Method: allocAndInit
diff --git a/src/net/java/sip/communicator/impl/shutdowntimeout/ShutdownTimeout.java b/src/net/java/sip/communicator/impl/shutdowntimeout/ShutdownTimeout.java
index e97cfb4..ea8cac8 100644
--- a/src/net/java/sip/communicator/impl/shutdowntimeout/ShutdownTimeout.java
+++ b/src/net/java/sip/communicator/impl/shutdowntimeout/ShutdownTimeout.java
@@ -30,9 +30,15 @@ public class ShutdownTimeout
= Logger.getLogger(ShutdownTimeout.class);
/**
+ * The system property which can be used to set custom timeout.
+ */
+ public static String SHUTDOWN_TIMEOUT_PROP =
+ "org.jitsi.shutdown.SHUTDOWN_TIMEOUT";
+
+ /**
* The number of miliseconds that we wait before we force a shutdown.
*/
- public static final long SHUTDOWN_TIMEOUT = 15000;//ms
+ public static final long SHUTDOWN_TIMEOUT_DEFAULT = 3000;//ms
/**
* The code that we exit with if the application is not down in 15 seconds.
@@ -72,11 +78,31 @@ public class ShutdownTimeout
{
synchronized(this)
{
- try{
+ try
+ {
+
+ long shutDownTimeout = SHUTDOWN_TIMEOUT_DEFAULT;
+
+ // check for custom value available through system
+ // property
+ try
+ {
+ String shutdownCustomValue =
+ System.getProperty(SHUTDOWN_TIMEOUT_PROP);
+
+ if(shutdownCustomValue != null
+ && shutdownCustomValue.length() > 0)
+ {
+ shutDownTimeout =
+ Long.valueOf(shutdownCustomValue);
+ }
+ }
+ catch(Throwable t){}
+
if (logger.isTraceEnabled())
logger.trace("Starting shutdown countdown of "
- + SHUTDOWN_TIMEOUT + "ms.");
- wait(SHUTDOWN_TIMEOUT);
+ + shutDownTimeout + "ms.");
+ wait(shutDownTimeout);
logger.error("Failed to gently shutdown. Forcing exit.");
System.exit(SYSTEM_EXIT_CODE);
}catch (InterruptedException ex){
diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityEventDispatcher.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityEventDispatcher.java
index 8e091a5..4255eb7 100644
--- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityEventDispatcher.java
+++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityEventDispatcher.java
@@ -117,6 +117,25 @@ public class SystemActivityEventDispatcher
}
/**
+ * Delivers the specified event to all registered listeners. Without
+ * using the thread, but delivering them in the calling thread.
+ *
+ * @param evt the <tt>SystemActivityEvent</tt> that we'd like delivered to
+ * all registered message listeners.
+ */
+ protected void fireSystemActivityEventCurrentThread(SystemActivityEvent evt)
+ {
+ List<SystemActivityChangeListener> listenersCopy = new ArrayList
+ <SystemActivityChangeListener>(listeners);
+ for (int i = 0; i < listenersCopy.size(); i++)
+ {
+ fireSystemActivityEvent(
+ evt,
+ listenersCopy.get(i));
+ }
+ }
+
+ /**
* Delivers the specified event to all registered listeners.
*
* @param evt the <tt>SystemActivityEvent</tt> that we'd like delivered to
diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java
index b7682c5..4f207e6 100644
--- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java
+++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java
@@ -69,6 +69,18 @@ public class SystemActivityNotifications
public static final int NOTIFY_DNS_CHANGE = 10;
/**
+ * Notifies for start of process of ending desktop session,
+ * logoff or shutdown.
+ */
+ public static final int NOTIFY_QUERY_ENDSESSION = 11;
+
+ /**
+ * All processes have been informed about ending session, now notify for
+ * the actual end session.
+ */
+ public static final int NOTIFY_ENDSESSION = 12;
+
+ /**
* The logger.
*/
private static Logger logger = Logger.getLogger(
diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
index e8891ad..67ec098 100644
--- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
+++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
@@ -278,6 +278,30 @@ public class SystemActivityNotificationsServiceImpl
SystemActivityEvent.EVENT_DNS_CHANGE);
break;
}
+ case SystemActivityNotifications.NOTIFY_QUERY_ENDSESSION :
+ {
+ // both events QUERY_ENDSESSION and ENDSESSION
+ // depend on the result one after another
+ // we don't put them in new thread in order to give control
+ // in the bundles using this events.
+ evt = new SystemActivityEvent(this,
+ SystemActivityEvent.EVENT_QUERY_ENDSESSION);
+ eventDispatcher.fireSystemActivityEventCurrentThread(evt);
+
+ return;
+ }
+ case SystemActivityNotifications.NOTIFY_ENDSESSION :
+ {
+ // both events QUERY_ENDSESSION and ENDSESSION
+ // depend on the result one after another
+ // we don't put them in new thread in order to give control
+ // in the bundles using this events.
+ evt = new SystemActivityEvent(this,
+ SystemActivityEvent.EVENT_ENDSESSION);
+ eventDispatcher.fireSystemActivityEventCurrentThread(evt);
+
+ return;
+ }
}
if (evt != null)
diff --git a/src/net/java/sip/communicator/plugin/windowscleanshutdown/CleanShutdownActivator.java b/src/net/java/sip/communicator/plugin/windowscleanshutdown/CleanShutdownActivator.java
new file mode 100644
index 0000000..7c64243
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/windowscleanshutdown/CleanShutdownActivator.java
@@ -0,0 +1,224 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.plugin.windowscleanshutdown;
+
+import net.java.sip.communicator.service.shutdown.*;
+import net.java.sip.communicator.service.sysactivity.*;
+import net.java.sip.communicator.service.sysactivity.event.*;
+import net.java.sip.communicator.util.*;
+import org.osgi.framework.*;
+
+import java.util.concurrent.*;
+
+/**
+ * Tries to cleanly close the application on shutdown/logoff. The events used
+ * here are only available on windows.
+ *
+ * If the application is still running once end session event is received
+ * and we have give it time (currently 3 sec.) we System.exit() the application.
+ *
+ * @author Emil Ivov
+ */
+public class CleanShutdownActivator
+ implements BundleActivator, ServiceListener
+{
+ private static final Logger logger
+ = Logger.getLogger(CleanShutdownActivator.class);
+
+ /**
+ * Used to wait for stop.
+ */
+ final CountDownLatch synchShutdown = new CountDownLatch(1);
+
+ /**
+ * Our context.
+ */
+ private BundleContext context;
+
+ /**
+ * The system activity service.
+ */
+ SystemActivityNotificationsService sysActivityService = null;
+
+ /**
+ * Bundle activator start method.
+ *
+ * @throws Exception If this method throws an exception
+ * (which won't happen).
+ */
+ public void start(final BundleContext context)
+ throws Exception
+ {
+ this.context = context;
+
+ logger.info("Starting the CleanShutdown service.");
+
+ handleNewSystemActivityNotificationsService(
+ getSystemActivityNotificationsService(context));
+
+ // if missing will wait for it
+ if(sysActivityService == null)
+ context.addServiceListener(this);
+ }
+
+ /**
+ * Called when this bundle is stopped so the Framework can perform the
+ * bundle-specific activities necessary to stop the bundle.
+ *
+ * @param context The execution context of the bundle being stopped.
+ * @throws Exception If this method throws an exception, the bundle is
+ * still marked as stopped, and the Framework will remove the bundle's
+ * listeners, unregister all services registered by the bundle, and
+ * release all services used by the bundle.
+ */
+ public void stop(BundleContext context)
+ throws Exception
+ {
+ // stop received.
+ synchShutdown.countDown();
+ }
+
+ /**
+ * Gets a reference to a <code>ShutdownService</code> implementation
+ * currently registered in the bundle context of the active
+ * <code>OsDependentActivator</code> instance.
+ * <p>
+ * The returned reference to <code>ShutdownService</code> is not being
+ * cached.
+ * </p>
+ *
+ * @return reference to a <code>ShutdownService</code> implementation
+ * currently registered in the bundle context of the active
+ * <code>OsDependentActivator</code> instance
+ */
+ private ShutdownService getShutdownService()
+ {
+ return(ShutdownService)context.getService(
+ context.getServiceReference(ShutdownService.class.getName()));
+ }
+
+ /**
+ * Gets a reference to a <code>SystemActivityNotificationsService</code>
+ * implementation currently registered in the bundle context.
+ * <p>
+ * The returned reference to <code>SystemActivityNotificationsService</code>
+ * is not being cached.
+ * </p>
+ *
+ * @param context the bundle context.
+ * @return reference to a <code>SystemActivityNotificationsService</code>
+ * implementation currently registered in the bundle context.
+ */
+ public static SystemActivityNotificationsService
+ getSystemActivityNotificationsService(BundleContext context)
+ {
+ ServiceReference ref =
+ context.getServiceReference(
+ SystemActivityNotificationsService.class.getName());
+
+ if(ref == null)
+ return null;
+ else
+ return
+ (SystemActivityNotificationsService)
+ context.getService(ref);
+ }
+
+
+ /**
+ * Saves the reference for the service and
+ * add a listener if the desired events are supported. Or start
+ * the checking thread otherwise.
+ * @param newService the service
+ */
+ private void handleNewSystemActivityNotificationsService
+ (SystemActivityNotificationsService newService)
+ {
+ sysActivityService = newService;
+
+ if(newService != null)
+ newService.addSystemActivityChangeListener(
+ new SystemActivityChangeListener()
+ {
+ public void activityChanged(SystemActivityEvent event)
+ {
+ if(event.getEventID()
+ == SystemActivityEvent.EVENT_QUERY_ENDSESSION)
+ {
+ // instruct the shutdown timeout to
+ // wait only 3 secs.
+ System.setProperty(
+ "org.jitsi.shutdown.SHUTDOWN_TIMEOUT",
+ "3000");
+
+ getShutdownService().beginShutdown();
+
+ // just wait a moment, or till we are stopped
+ try
+ {
+ synchronized(this)
+ {
+ synchShutdown.await(1500,
+ TimeUnit.MILLISECONDS);
+ }
+ }
+ catch(Throwable t)
+ {}
+ }
+ else if(event.getEventID()
+ == SystemActivityEvent.EVENT_ENDSESSION)
+ {
+ try
+ {
+ // wait till we are stopped or forced stopped
+ synchShutdown.await();
+ }
+ catch(Throwable t)
+ {}
+ }
+ }
+ });
+ }
+
+ /**
+ * When new SystemActivityNotificationsService
+ * is registered we add needed listeners.
+ *
+ * @param serviceEvent ServiceEvent
+ */
+ public void serviceChanged(ServiceEvent serviceEvent)
+ {
+ ServiceReference serviceRef = serviceEvent.getServiceReference();
+
+ // if the event is caused by a bundle being stopped, we don't want to
+ // know we are shutting down
+ if (serviceRef.getBundle().getState() == Bundle.STOPPING)
+ {
+ return;
+ }
+
+ Object sService = context
+ .getService(serviceRef);
+
+ if(sService instanceof SystemActivityNotificationsService)
+ {
+ switch (serviceEvent.getType())
+ {
+ case ServiceEvent.REGISTERED:
+ handleNewSystemActivityNotificationsService(
+ (SystemActivityNotificationsService)sService);
+ break;
+ case ServiceEvent.UNREGISTERING:
+ //((SystemActivityNotificationsService)sService)
+ // .removeSystemActivityChangeListener(this);
+ break;
+ }
+
+ return;
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/windowscleanshutdown/cleanshutdown.manifest.mf b/src/net/java/sip/communicator/plugin/windowscleanshutdown/cleanshutdown.manifest.mf
new file mode 100644
index 0000000..25db59f
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/windowscleanshutdown/cleanshutdown.manifest.mf
@@ -0,0 +1,12 @@
+Bundle-Activator: net.java.sip.communicator.plugin.windowscleanshutdown.CleanShutdownActivator
+Bundle-Name: CleanShutdownBundle
+Bundle-Description: A bundle that makes sure that when closed Jitsi will exit cleanly.
+Bundle-Vendor: jitsi.org
+Bundle-Version: 0.0.1
+System-Bundle: yes
+Import-Package: org.osgi.framework,
+ org.jitsi.service.configuration,
+ net.java.sip.communicator.service.shutdown,
+ net.java.sip.communicator.service.sysactivity,
+ net.java.sip.communicator.service.sysactivity.event,
+ net.java.sip.communicator.util
diff --git a/src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java b/src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java
index 49494b0..36f85b9 100644
--- a/src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java
+++ b/src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java
@@ -87,6 +87,19 @@ public class SystemActivityEvent
public static final int EVENT_DNS_CHANGE = 12;
/**
+ * Informing that the machine is logging of or shutting down.
+ */
+ public static final int EVENT_QUERY_ENDSESSION = 13;
+
+ /**
+ * The log off or shutdown is in process for us, no matter
+ * what other process has replied, whether one of them has canceled
+ * or not the current end of session. It's like that cause we have answered
+ * that we will shutdown.
+ */
+ public static final int EVENT_ENDSESSION = 14;
+
+ /**
* The type of the event.
*/
private final int eventID;