Modified: 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java?rev=1725510&r1=1725509&r2=1725510&view=diff
==============================================================================
--- 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java 
(original)
+++ 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java 
Tue Jan 19 12:59:03 2016
@@ -18,10 +18,11 @@
  */
 package org.apache.felix.gogo.shell;
 
+import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.HashSet;
 import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -43,7 +44,8 @@ public class Activator implements Bundle
     private ServiceTracker commandProcessorTracker;
     private Set<ServiceRegistration> regs;
 
-    private ExecutorService executor;
+    private volatile ExecutorService executor;
+    private volatile StartShellJob shellJob;
 
     public Activator()
     {
@@ -59,17 +61,21 @@ public class Activator implements Bundle
 
     public void stop(BundleContext context) throws Exception
     {
-        Iterator<ServiceRegistration> iterator = regs.iterator();
-        while (iterator.hasNext())
+        Set<ServiceRegistration> currentRegs = new 
HashSet<ServiceRegistration>();
+        synchronized (regs)
         {
-            ServiceRegistration reg = iterator.next();
-            reg.unregister();
-            iterator.remove();
+            currentRegs.addAll(regs);
+            regs.clear();
         }
 
-        stopShell();
+        for (ServiceRegistration reg : currentRegs)
+        {
+            reg.unregister();
+        }
 
         this.commandProcessorTracker.close();
+
+        stopShell();
     }
 
     private ServiceTracker createCommandProcessorTracker()
@@ -98,26 +104,34 @@ public class Activator implements Bundle
         Dictionary<String, Object> dict = new Hashtable<String, Object>();
         dict.put(CommandProcessor.COMMAND_SCOPE, "gogo");
 
+        Set<ServiceRegistration> currentRegs = new 
HashSet<ServiceRegistration>();
+
         // register converters
-        regs.add(context.registerService(Converter.class.getName(), new 
Converters(context.getBundle(0).getBundleContext()), null));
+        currentRegs.add(context.registerService(Converter.class.getName(), new 
Converters(context.getBundle(0).getBundleContext()), null));
 
         // register commands
 
         dict.put(CommandProcessor.COMMAND_FUNCTION, Builtin.functions);
-        regs.add(context.registerService(Builtin.class.getName(), new 
Builtin(), dict));
+        currentRegs.add(context.registerService(Builtin.class.getName(), new 
Builtin(), dict));
 
         dict.put(CommandProcessor.COMMAND_FUNCTION, Procedural.functions);
-        regs.add(context.registerService(Procedural.class.getName(), new 
Procedural(), dict));
+        currentRegs.add(context.registerService(Procedural.class.getName(), 
new Procedural(), dict));
 
         dict.put(CommandProcessor.COMMAND_FUNCTION, Posix.functions);
-        regs.add(context.registerService(Posix.class.getName(), new Posix(), 
dict));
+        currentRegs.add(context.registerService(Posix.class.getName(), new 
Posix(), dict));
 
         dict.put(CommandProcessor.COMMAND_FUNCTION, Telnet.functions);
-        regs.add(context.registerService(Telnet.class.getName(), new 
Telnet(processor), dict));
+        currentRegs.add(context.registerService(Telnet.class.getName(), new 
Telnet(processor), dict));
 
         Shell shell = new Shell(context, processor);
         dict.put(CommandProcessor.COMMAND_FUNCTION, Shell.functions);
-        regs.add(context.registerService(Shell.class.getName(), shell, dict));
+        currentRegs.add(context.registerService(Shell.class.getName(), shell, 
dict));
+
+        synchronized (regs)
+        {
+            regs.addAll(currentRegs);
+            currentRegs.clear();
+        }
 
         // start shell on a separate thread...
         executor = Executors.newSingleThreadExecutor(new ThreadFactory()
@@ -127,20 +141,31 @@ public class Activator implements Bundle
                 return new Thread(runnable, "Gogo shell");
             }
         });
-        executor.submit(new StartShellJob(context, processor));
+        shellJob = new StartShellJob(context, processor);
+        executor.submit(shellJob);
     }
 
     private void stopShell()
     {
         if (executor != null && !(executor.isShutdown() || 
executor.isTerminated()))
         {
-            executor.shutdownNow();
+            if (shellJob != null)
+            {
+                shellJob.terminate();
+            }
+            executor.shutdown();
 
             try
             {
                 if (!executor.awaitTermination(5, TimeUnit.SECONDS))
                 {
                     System.err.println("!!! FAILED TO STOP EXECUTOR !!!");
+                    Map<Thread, StackTraceElement[]> allStackTraces = 
Thread.getAllStackTraces();
+                    for (Map.Entry<Thread, StackTraceElement[]> entry : 
allStackTraces.entrySet())
+                    {
+                        Thread t = entry.getKey();
+                        System.err.printf("Thread: %s (%s): %s\n", 
t.getName(), t.getState(), Arrays.toString(entry.getValue()));
+                    }
                 }
             }
             catch (InterruptedException e)
@@ -156,6 +181,7 @@ public class Activator implements Bundle
     {
         private final BundleContext context;
         private final CommandProcessor processor;
+        private volatile CommandSession session;
 
         public StartShellJob(BundleContext context, CommandProcessor processor)
         {
@@ -165,7 +191,7 @@ public class Activator implements Bundle
 
         public void run()
         {
-            CommandSession session = processor.createSession(System.in, 
System.out, System.err);
+            session = processor.createSession(System.in, System.out, 
System.err);
             try
             {
                 // wait for gosh command to be registered
@@ -178,6 +204,11 @@ public class Activator implements Bundle
                 args = (args == null) ? "" : args;
                 session.execute("gosh --login " + args);
             }
+            catch (InterruptedException e)
+            {
+                // Ok, back off...
+                Thread.currentThread().interrupt();
+            }
             catch (Exception e)
             {
                 Object loc = session.get(".location");
@@ -191,8 +222,18 @@ public class Activator implements Bundle
             }
             finally
             {
+                terminate();
+            }
+        }
+
+        public void terminate()
+        {
+            if (session != null)
+            {
                 session.close();
+                session = null;
             }
+            Thread.currentThread().interrupt();
         }
     }
 }
\ No newline at end of file

Modified: 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Console.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Console.java?rev=1725510&r1=1725509&r2=1725510&view=diff
==============================================================================
--- 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Console.java 
(original)
+++ 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Console.java 
Tue Jan 19 12:59:03 2016
@@ -32,7 +32,7 @@ public class Console implements Runnable
     private final InputStream in;
     private final PrintStream out;
     private final History history;
-    private boolean quit;
+    private volatile boolean quit;
 
     public Console(CommandSession session, History history)
     {
@@ -46,7 +46,7 @@ public class Console implements Runnable
     {
         try
         {
-            while (!quit)
+            while (!Thread.currentThread().isInterrupted() && !quit)
             {
                 CharSequence line = getLine(getPrompt());
 
@@ -95,8 +95,7 @@ public class Console implements Runnable
                             loc = "gogo";
                         }
 
-                        out.println(loc + ": " + e.getClass().getSimpleName() 
+ ": "
-                            + e.getMessage());
+                        out.println(loc + ": " + e.getClass().getSimpleName() 
+ ": " + e.getMessage());
                     }
                 }
                 finally
@@ -146,7 +145,20 @@ public class Console implements Runnable
         while (!quit)
         {
             out.flush();
-            int c = in.read();
+
+            int c = 0;
+            try
+            {
+                c = in.read();
+            }
+            catch (IOException e)
+            {
+                if ("Stream closed".equals(e.getMessage())) {
+                    quit = true;
+                } else {
+                    throw e;
+                }
+            }
 
             switch (c)
             {

Modified: 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Converters.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Converters.java?rev=1725510&r1=1725509&r2=1725510&view=diff
==============================================================================
--- 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Converters.java
 (original)
+++ 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Converters.java
 Tue Jan 19 12:59:03 2016
@@ -24,19 +24,19 @@ import java.lang.reflect.InvocationHandl
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.Arrays;
-import java.util.Formatter;
 
+import org.apache.felix.service.command.Converter;
+import org.apache.felix.service.command.Function;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.apache.felix.service.command.Converter;
-import org.apache.felix.service.command.Function;
 import org.osgi.service.startlevel.StartLevel;
 
 public class Converters implements Converter
 {
     private final BundleContext context;
+
     public Converters(BundleContext context)
     {
         this.context = context;
@@ -67,9 +67,6 @@ public class Converters implements Conve
 
     private CharSequence print(ServiceReference ref)
     {
-        StringBuilder sb = new StringBuilder();
-        Formatter f = new Formatter(sb);
-
         String spid = "";
         Object pid = ref.getProperty("service.pid");
         if (pid != null)
@@ -77,10 +74,9 @@ public class Converters implements Conve
             spid = pid.toString();
         }
 
-        f.format("%06d %3s %-40s %s", ref.getProperty("service.id"),
+        return String.format("%06d %3s %-40s %s", 
ref.getProperty("service.id"),
             ref.getBundle().getBundleId(),
             getShortNames((String[]) ref.getProperty("objectclass")), spid);
-        return sb;
     }
 
     private CharSequence getShortNames(String[] list)

Modified: 
felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Shell.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Shell.java?rev=1725510&r1=1725509&r2=1725510&view=diff
==============================================================================
--- felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Shell.java 
(original)
+++ felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Shell.java 
Tue Jan 19 12:59:03 2016
@@ -35,6 +35,7 @@ import org.apache.felix.gogo.options.Opt
 import org.apache.felix.gogo.options.Options;
 import org.apache.felix.service.command.CommandProcessor;
 import org.apache.felix.service.command.CommandSession;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
 
@@ -49,6 +50,8 @@ public class Shell
     private final CommandProcessor processor;
     private final History history;
 
+    private volatile Bundle systemBundle;
+
     public Shell(BundleContext context, CommandProcessor processor)
     {
         this.context = context;
@@ -79,6 +82,9 @@ public class Shell
         boolean login = opt.isSet("login");
         boolean interactive = !opt.isSet("nointeractive");
 
+        // We grab this bundle as early as possible to avoid having to deal 
with invalid bundleContexts of this bundle during shutdowns...
+        systemBundle = context.getBundle(0);
+
         if (opt.isSet("help"))
         {
             opt.usage();
@@ -94,8 +100,7 @@ public class Shell
             throw opt.usageError("option --command requires argument(s)");
         }
 
-        CommandSession newSession = (login ? session : processor.createSession(
-            session.getKeyboard(), session.getConsole(), System.err));
+        CommandSession newSession = (login ? session : 
processor.createSession(session.getKeyboard(), session.getConsole(), 
System.err));
 
         if (opt.isSet("xtrace"))
         {
@@ -108,7 +113,8 @@ public class Shell
             if (!new File(uri).exists())
             {
                 URL url = getClass().getResource("/ext/gosh_profile");
-                if (url == null) {
+                if (url == null)
+                {
                     url = getClass().getResource("/gosh_profile");
                 }
                 uri = (url == null) ? null : url.toURI();
@@ -173,10 +179,17 @@ public class Shell
             result = newSession.execute(program);
         }
 
-        if (login && interactive && !opt.isSet("noshutdown"))
+        if (login && interactive)
         {
-            System.out.println("gosh: stopping framework");
-            shutdown();
+            if (opt.isSet("noshutdown"))
+            {
+                System.out.println("gosh: stopping shell");
+            }
+            else
+            {
+                System.out.println("gosh: stopping shell and framework");
+                shutdown();
+            }
         }
 
         return result;
@@ -189,7 +202,11 @@ public class Shell
 
     private void shutdown() throws BundleException
     {
-        context.getBundle(0).stop();
+        if (systemBundle != null)
+        {
+            systemBundle.stop();
+            systemBundle = null;
+        }
     }
 
     public Object source(CommandSession session, String script) throws 
Exception
@@ -258,10 +275,12 @@ public class Shell
         }
     }
 
-    public String[] history() {
+    public String[] history()
+    {
         Iterator<String> history = this.history.getHistory();
         List<String> lines = new ArrayList<String>();
-        for (int i = 1; history.hasNext(); i++) {
+        for (int i = 1; history.hasNext(); i++)
+        {
             lines.add(String.format("%5d  %s", i, history.next()));
         }
         return lines.toArray(new String[lines.size()]);


Reply via email to