From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30323 invoked by alias); 13 Mar 2008 15:53:38 -0000 Received: (qmail 30296 invoked by uid 9519); 13 Mar 2008 15:53:37 -0000 Date: Thu, 13 Mar 2008 15:53:00 -0000 Message-ID: <20080313155337.30281.qmail@sourceware.org> From: rmoseley@sourceware.org To: frysk-cvs@sourceware.org Subject: [SCM] master: Add ability to kill a process using its PID. X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: f7bc2b759574fce3842b3b60fe473a9bb8b10431 X-Git-Newrev: 115cd21f235b29fe70e9da77c8a6298aab692569 Mailing-List: contact frysk-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: frysk-cvs-owner@sourceware.org Reply-To: frysk@sourceware.org X-SW-Source: 2008-q1/txt/msg00352.txt.bz2 The branch, master has been updated via 115cd21f235b29fe70e9da77c8a6298aab692569 (commit) from f7bc2b759574fce3842b3b60fe473a9bb8b10431 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 115cd21f235b29fe70e9da77c8a6298aab692569 Author: Rick Moseley Date: Thu Mar 13 10:52:46 2008 -0500 Add ability to kill a process using its PID. * KillCommand.java: Add ability to kill by PID. * TestKillCommand.java: Add test for above. ----------------------------------------------------------------------- Summary of changes: frysk-core/frysk/hpd/ChangeLog | 3 + frysk-core/frysk/hpd/KillCommand.java | 112 ++++++++++++++++++++--------- frysk-core/frysk/hpd/TestKillCommand.java | 69 ++++++++++++++---- 3 files changed, 138 insertions(+), 46 deletions(-) First 500 lines of diff: diff --git a/frysk-core/frysk/hpd/ChangeLog b/frysk-core/frysk/hpd/ChangeLog index d4a47a1..406d23d 100644 --- a/frysk-core/frysk/hpd/ChangeLog +++ b/frysk-core/frysk/hpd/ChangeLog @@ -2,6 +2,9 @@ * CLI.java: Synchronize message adding when type specified. * LoadCommand.java: Use message logger instead of direct print. + + * KillCommand.java: Add ability to kill by PID. + * TestKillCommand.java: Add test for above. 2008-03-10 Mark Wielaard diff --git a/frysk-core/frysk/hpd/KillCommand.java b/frysk-core/frysk/hpd/KillCommand.java index 13f9bfd..26f11b2 100644 --- a/frysk-core/frysk/hpd/KillCommand.java +++ b/frysk-core/frysk/hpd/KillCommand.java @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2007, 2008, Red Hat Inc. +// Copyright 2007, 2008 Red Hat Inc. // // FRYSK is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by @@ -39,11 +39,9 @@ package frysk.hpd; -//import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.TreeMap; import frysk.proc.Proc; import frysk.proc.Task; import java.util.List; @@ -53,54 +51,102 @@ import java.util.List; */ public class KillCommand extends ParameterizedCommand { - private static String full = "kill the processes that are currently in " + - "the current target set. The processes are then reloaded and then " + - "ready to be run again."; + private static String full = "kill [PID]\n" + + "kill the processes that are currently in " + + "the current target set or kill a specific PID. If kill is run " + + "without parameters, all processes in the current target set are " + + "killed and then reloaded and are then ready to be run again."; + + Map saveProcs = new HashMap(); KillCommand() { - super("kill the current targetset", "kill", full); + super("kill the current targetset or kill a specific PID", "kill", full); } public void interpret(CLI cli, Input cmd, Object options) { - Map saveProcs = new HashMap(); - saveProcs = new TreeMap(); + if (cmd.size() > 2) + throw new InvalidCommandException("Too many parameters"); + + switch (cmd.size()) { + + case 0: + + killProc(-1, cli); + cli.outWriter.flush(); + + synchronized (cli) { + // Clear the running procs set + cli.runningProcs.clear(); + // Clear the stepping engine structures + cli.steppingEngine.clear(); + // Add back in the stepping observer for cli + cli.steppingEngine.addObserver(cli.steppingObserver); + } + // Now loop through and re-load all of the killed procs + Iterator bar = saveProcs.keySet().iterator(); + while (bar.hasNext()) { + Integer procId = (Integer) bar.next(); + String cmdline = (String) saveProcs.get(procId); + cli.taskID = procId.intValue(); + cli.execCommand("load " + cmdline + "\n"); + } + cli.taskID = -1; + break; + + // This is the case where a PID was entered + case 1: + int pid; + try { + pid = Integer.parseInt(cmd.parameter(0)); + } catch (NumberFormatException e) { + cli.addMessage("PID entered is not an integer", Message.TYPE_ERROR); + return; + } + if (!killProc(pid, cli)) + cli.addMessage("PID " + pid + " could not be found", Message.TYPE_ERROR); + } + } + + /** + * killProc will kill all Procs or just the Proc specified by the PID + * passed to it. + * + * @param pid + * is an int containing the PID that should be killed, if + * pid < 0, kill all the PIDs frysk in targetset, else just + * kill the process of the specified PID. + * @param cli + * is the current command line interface object + */ + + boolean killProc(int pid, CLI cli) { int procPID = 0; Iterator foo = cli.targetset.getTaskData(); while (foo.hasNext()) { TaskData taskData = (TaskData) foo.next(); Task task = taskData.getTask(); Proc proc = task.getProc(); - if (proc.getPid() != procPID) { - cli.outWriter.println("Killing process " + proc.getPid() - + " that was created from " - + proc.getExe()); + if ((proc.getPid() != procPID && pid < 0) || + proc.getPid() == pid) { + cli.addMessage("Killing process " + proc.getPid() + + " that was created from " + proc.getExe(), + Message.TYPE_NORMAL); + cli.outWriter.flush(); // Save the procs we are killing so we can re-load them later - saveProcs.put(new Integer(taskData.getParentID()), - proc.getExe()); + saveProcs.put(new Integer(taskData.getParentID()), proc + .getExe()); procPID = proc.getPid(); // Now, call the Proc object to kill off the executable(s) proc.requestKill(); + if ((pid > 0)) + return true; } } - - synchronized (cli) { - // Clear the running procs set - cli.runningProcs.clear(); - // Clear the stepping engine structures - cli.steppingEngine.clear(); - // Add back in the stepping observer for cli - cli.steppingEngine.addObserver(cli.steppingObserver); - } - // Now loop through and re-load all of the killed procs - Iterator bar = saveProcs.keySet().iterator(); - while (bar.hasNext()) { - Integer procId = (Integer) bar.next(); - String cmdline = (String) saveProcs.get(procId); - cli.taskID = procId.intValue(); - cli.execCommand("load " + cmdline + "\n"); - } - cli.taskID = -1; + // If we got to here and pid > 0 then we did not find that PID + if (pid > 0) + return false; + return true; } int completer(CLI cli, Input input, int cursor, List completions) { diff --git a/frysk-core/frysk/hpd/TestKillCommand.java b/frysk-core/frysk/hpd/TestKillCommand.java index 5c1eedf..13ccecd 100644 --- a/frysk-core/frysk/hpd/TestKillCommand.java +++ b/frysk-core/frysk/hpd/TestKillCommand.java @@ -40,10 +40,10 @@ package frysk.hpd; import frysk.config.Config; +import frysk.testbed.SlaveOffspring; /** - * This class tests the "load" command basics of both loading a correct - * executable and trying to load a non-existent executable. + * This class tests the "kill" command basics. */ public class TestKillCommand extends TestLib { @@ -151,21 +151,64 @@ public class TestKillCommand extends TestLib { e.sendCommandExpectPrompt("kill", "Killing process.*"); /* Adding the quit/Quitting lines causes the following stack trace: - frysk.expunit.EndOfFileException: end-of-file; expecting: <>; buffer <>; buffer <> + at frysk.expunit.Child.expectMilliseconds(Child.java:161) + at frysk.expunit.Expect.expect(Expect.java:158) + at frysk.expunit.Expect.expect(Expect.java:167) + at frysk.expunit.Expect.expect(Expect.java:176) + at frysk.hpd.TestKillCommand.testLoadKill(TestKillCommand.java:170) + at frysk.junit.Runner.runCases(Runner.java:197) + at frysk.junit.Runner.runTestCases(Runner.java:424) + at TestRunner.main(TestRunner.java:63) */ //e.send("quit\n"); //e.expect("Quitting\\.\\.\\..*"); e.close(); } + /** + * Test killing of a single proc using the PID + */ + public void testKillByPID() { + SlaveOffspring newProc = SlaveOffspring.createDaemon(); + int pid = newProc.getPid().intValue(); + e = new HpdTestbed(); + e.sendCommandExpectPrompt("attach " + pid, "Attached to process " + pid + ".*"); + e.sendCommandExpectPrompt("kill " + pid, "Killing process " + pid + ".*"); + try { Thread.sleep(500); } catch (Exception e) { } + e.sendCommandExpectPrompt("kill " + pid, "PID " + pid + " could not be found.*"); + e.send("quit\n"); + e.expect("Quitting\\.\\.\\..*"); + e.close(); + } + + public void testKillError() { + SlaveOffspring newProc = SlaveOffspring.createDaemon(); + int pid = newProc.getPid().intValue(); + e = new HpdTestbed(); + e.sendCommandExpectPrompt("attach " + pid, "Attached to process " + pid + ".*"); + e.sendCommandExpectPrompt("kill abc", "Error: PID entered is not an integer.*"); + e.send("quit\n"); + e.expect("Quitting\\.\\.\\..*"); + e.close(); + } + + public void testKillErrorTwo() { + e = new HpdTestbed(); + e.sendCommandExpectPrompt("kill a b c", "Too many parameters.*"); + } + } hooks/post-receive -- frysk system monitor/debugger