Compare commits
No commits in common. "92fb02b0bf81196266fc0a72c2f2b600a78a1b15" and "0b8cf633ee360e02fedd0ba57b396895567d6793" have entirely different histories.
92fb02b0bf
...
0b8cf633ee
6 changed files with 76 additions and 80 deletions
|
|
@ -17,13 +17,8 @@ compile:
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script: "./gradlew test"
|
||||||
- "./certs-gen.sh"
|
|
||||||
- "./gradlew test"
|
|
||||||
|
|
||||||
package:
|
package:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
script:
|
script: "./package.sh"
|
||||||
- "./certs-gen.sh"
|
|
||||||
- "./gradlew build"
|
|
||||||
- "./package.sh"
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
./certs-gen.sh
|
|
||||||
./gradlew clean build
|
|
||||||
./package.sh
|
|
||||||
|
|
@ -13,7 +13,6 @@ if [ -z "$CLTNAME" ]; then
|
||||||
CLTNAME=localhost
|
CLTNAME=localhost
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
SERVER_CA_CN=jobserv-server-ca
|
SERVER_CA_CN=jobserv-server-ca
|
||||||
SERVER_PATH=resources/server
|
SERVER_PATH=resources/server
|
||||||
CLIENT_CA_CN=jobserv-client-ca
|
CLIENT_CA_CN=jobserv-client-ca
|
||||||
|
|
@ -96,4 +95,3 @@ echo "[+] Converting private keys to X.509"
|
||||||
openssl pkcs8 -topk8 -nocrypt -in $CLIENT_PATH/private.key -out $CLIENT_PATH/private.pem
|
openssl pkcs8 -topk8 -nocrypt -in $CLIENT_PATH/private.key -out $CLIENT_PATH/private.pem
|
||||||
openssl pkcs8 -topk8 -nocrypt -in $SERVER_PATH/private.key -out $SERVER_PATH/private.pem
|
openssl pkcs8 -topk8 -nocrypt -in $SERVER_PATH/private.key -out $SERVER_PATH/private.pem
|
||||||
openssl pkcs8 -topk8 -nocrypt -in $TEST_PATH/private.key -out $TEST_PATH/private.pem
|
openssl pkcs8 -topk8 -nocrypt -in $TEST_PATH/private.key -out $TEST_PATH/private.pem
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,11 @@
|
||||||
|
|
||||||
package JobServ;
|
package JobServ;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.io.BufferedReader;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ProcessController
|
* ProcessController
|
||||||
|
|
@ -36,23 +33,18 @@ class ProcessController {
|
||||||
private BufferedReader reader;
|
private BufferedReader reader;
|
||||||
|
|
||||||
private Process process;
|
private Process process;
|
||||||
private Boolean killedManually = false;
|
|
||||||
|
|
||||||
private Lock lock;
|
private Boolean killedManually = false;
|
||||||
private int lockTimeout; // seconds
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor
|
* Constructor
|
||||||
* Takes a command and spawns it in a new process
|
* Takes a command and spawns it in a new process
|
||||||
* Redirects IO streams and assigns a fake PID
|
* Redirects IO streams and assigns a fake PID
|
||||||
*/
|
*/
|
||||||
public ProcessController(String command, int lockTimeout) throws IOException {
|
public ProcessController(String command) throws IOException {
|
||||||
this.pid = ProcessController.nextPid;
|
this.pid = ProcessController.nextPid;
|
||||||
ProcessController.nextPid += 1;
|
ProcessController.nextPid += 1;
|
||||||
|
|
||||||
this.lock = new ReentrantLock();
|
|
||||||
this.lockTimeout = lockTimeout;
|
|
||||||
|
|
||||||
this.process = Runtime.getRuntime().exec(command);
|
this.process = Runtime.getRuntime().exec(command);
|
||||||
this.output = this.process.getOutputStream();
|
this.output = this.process.getOutputStream();
|
||||||
this.input = this.process.getInputStream();
|
this.input = this.process.getInputStream();
|
||||||
|
|
@ -62,28 +54,6 @@ class ProcessController {
|
||||||
JobServServer.logger.write("Job " + String.valueOf(this.pid) + ": " + command);
|
JobServServer.logger.write("Job " + String.valueOf(this.pid) + ": " + command);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* getLock()
|
|
||||||
* attempts to get the lock for lockTimeout seconds
|
|
||||||
* or throws exceptions if interrupted
|
|
||||||
*/
|
|
||||||
public boolean getLock() throws InterruptedException {
|
|
||||||
return this.lock.tryLock(this.lockTimeout, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* releaseLock()
|
|
||||||
* releases lock on process
|
|
||||||
*/
|
|
||||||
public void releaseLock() {
|
|
||||||
try {
|
|
||||||
this.lock.unlock();
|
|
||||||
|
|
||||||
} catch (IllegalMonitorStateException e) {
|
|
||||||
JobServServer.logger.write("Thread tried to release a lock it didnt have! " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getPid()
|
* getPid()
|
||||||
* returns translated pid of this process
|
* returns translated pid of this process
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ class ProcessManager {
|
||||||
* processMap
|
* processMap
|
||||||
*/
|
*/
|
||||||
protected ConcurrentHashMap<Integer, ProcessController> processMap;
|
protected ConcurrentHashMap<Integer, ProcessController> processMap;
|
||||||
|
protected ConcurrentHashMap<Integer, Boolean> lockMap;
|
||||||
private ExecutorService threadPool = Executors.newCachedThreadPool();
|
private ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -48,6 +49,7 @@ class ProcessManager {
|
||||||
*/
|
*/
|
||||||
public ProcessManager() {
|
public ProcessManager() {
|
||||||
processMap = new ConcurrentHashMap<Integer, ProcessController>();
|
processMap = new ConcurrentHashMap<Integer, ProcessController>();
|
||||||
|
lockMap = new ConcurrentHashMap<Integer, Boolean>();
|
||||||
/* TODO: In a long running server over a large period of time
|
/* TODO: In a long running server over a large period of time
|
||||||
* It is possible that the streams used to redirect IO in the
|
* It is possible that the streams used to redirect IO in the
|
||||||
* Processes may become a significant use of resources.
|
* Processes may become a significant use of resources.
|
||||||
|
|
@ -66,8 +68,12 @@ class ProcessManager {
|
||||||
public int newProcess(String command) {
|
public int newProcess(String command) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ProcessController newProc = new ProcessController(command, this.LOCK_TIMEOUT);
|
ProcessController newProc = new ProcessController(command);
|
||||||
|
// we dont need to lock the map yet
|
||||||
|
this.lockMap.put(newProc.getPid(), true);
|
||||||
this.processMap.put(newProc.getPid(), newProc);
|
this.processMap.put(newProc.getPid(), newProc);
|
||||||
|
|
||||||
|
this.releaseLock(newProc.getPid());
|
||||||
return newProc.getPid();
|
return newProc.getPid();
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
@ -89,13 +95,14 @@ class ProcessManager {
|
||||||
public int getProcessStatus(int pid) {
|
public int getProcessStatus(int pid) {
|
||||||
try {
|
try {
|
||||||
if(!this.getLock(pid)) {
|
if(!this.getLock(pid)) {
|
||||||
// lock could not be grabbed before timeout
|
return 3;
|
||||||
JobServServer.logger.write("Timeout getting process status: " + String.valueOf(pid));
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (TimeoutException e) {
|
||||||
return 3;
|
// lock could not be grabbed before timeout
|
||||||
|
JobServServer.logger.write("Timeout getting process " +
|
||||||
|
String.valueOf(pid) + " status: " + e.getMessage());
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessController candidate = this.processMap.get(pid);
|
ProcessController candidate = this.processMap.get(pid);
|
||||||
|
|
@ -116,12 +123,13 @@ class ProcessManager {
|
||||||
public int getProcessReturn(int pid) {
|
public int getProcessReturn(int pid) {
|
||||||
try {
|
try {
|
||||||
if(!this.getLock(pid)) {
|
if(!this.getLock(pid)) {
|
||||||
JobServServer.logger.write("Timeout getting process return: " + String.valueOf(pid));
|
return 258;
|
||||||
return 259;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (TimeoutException e) {
|
||||||
return 258;
|
JobServServer.logger.write("Timeout getting process " +
|
||||||
|
String.valueOf(pid) + " return: " + e.getMessage());
|
||||||
|
return 259;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessController candidate = this.processMap.get(pid);
|
ProcessController candidate = this.processMap.get(pid);
|
||||||
|
|
@ -138,12 +146,13 @@ class ProcessManager {
|
||||||
public String getProcessOutput(int pid, int lines) {
|
public String getProcessOutput(int pid, int lines) {
|
||||||
try {
|
try {
|
||||||
if(!this.getLock(pid)) {
|
if(!this.getLock(pid)) {
|
||||||
JobServServer.logger.write("Timeout getting process output: " + String.valueOf(pid));
|
return "[-] SERVER: Process not found";
|
||||||
return "[-] SERVER: Timeout grabbing lock to access process information";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (TimeoutException e) {
|
||||||
return "[-] SERVER: Process not found";
|
JobServServer.logger.write("Timeout getting process " +
|
||||||
|
String.valueOf(pid) + " output: " + e.getMessage());
|
||||||
|
return "[-] SERVER: Timeout grabbing lock to access process information";
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessController candidate = this.processMap.get(pid);
|
ProcessController candidate = this.processMap.get(pid);
|
||||||
|
|
@ -163,13 +172,13 @@ class ProcessManager {
|
||||||
public int killProcess(int pid) {
|
public int killProcess(int pid) {
|
||||||
try {
|
try {
|
||||||
if(!this.getLock(pid)) {
|
if(!this.getLock(pid)) {
|
||||||
JobServServer.logger.write("Timeout killing process: " + String.valueOf(pid));
|
return 2;
|
||||||
return 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (TimeoutException e) {
|
||||||
|
JobServServer.logger.write("Timeout killing process " +
|
||||||
return 2;
|
String.valueOf(pid) + ": " + e.getMessage());
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessController candidate = this.processMap.get(pid);
|
ProcessController candidate = this.processMap.get(pid);
|
||||||
|
|
@ -185,20 +194,45 @@ class ProcessManager {
|
||||||
* Function is synchronized to prevent multiple threads accessing the same lock at once
|
* Function is synchronized to prevent multiple threads accessing the same lock at once
|
||||||
* (ConcurrentHashMap will report whatever lock value was last to successfully update)
|
* (ConcurrentHashMap will report whatever lock value was last to successfully update)
|
||||||
*/
|
*/
|
||||||
protected synchronized Boolean getLock(int pid) throws IndexOutOfBoundsException {
|
protected synchronized Boolean getLock(int pid) throws TimeoutException {
|
||||||
ProcessController candidate = this.processMap.get(pid);
|
if (!lockMap.containsKey(pid)) {
|
||||||
if (candidate == null) {
|
return false;
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Object> future = this.threadPool.submit(
|
||||||
|
new Callable<Object>() {
|
||||||
|
public Object call() {
|
||||||
|
while(lockMap.get(pid)) {
|
||||||
|
continue; // spin!
|
||||||
|
}
|
||||||
|
|
||||||
|
lockMap.replace(pid, true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Boolean success = candidate.getLock();
|
future.get(this.LOCK_TIMEOUT, TimeUnit.SECONDS);
|
||||||
return success;
|
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
JobServServer.logger.write("[!] Couldnt get lock " +
|
JobServServer.logger.write("[!] Couldnt get lock " +
|
||||||
String.valueOf(pid) + ": "+ e.getMessage());
|
String.valueOf(pid) + ": "+ e.getMessage());
|
||||||
|
future.cancel(true);
|
||||||
|
|
||||||
|
// in case lock was grabbed after exception
|
||||||
|
this.releaseLock(pid);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
JobServServer.logger.write("[!] Couldnt get lock " +
|
||||||
|
String.valueOf(pid) + ": "+ e.getMessage());
|
||||||
|
future.cancel(true);
|
||||||
|
|
||||||
|
// in case lock was grabbed after exception
|
||||||
|
this.releaseLock(pid);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// cancel the attempt to grab the lock
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -213,6 +247,8 @@ class ProcessManager {
|
||||||
* mediate access to the ProcessManager
|
* mediate access to the ProcessManager
|
||||||
* object for fresh calls as well.
|
* object for fresh calls as well.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -220,13 +256,7 @@ class ProcessManager {
|
||||||
* releases mutex so other threads can operate on processqueue
|
* releases mutex so other threads can operate on processqueue
|
||||||
*/
|
*/
|
||||||
protected void releaseLock(int pid) {
|
protected void releaseLock(int pid) {
|
||||||
ProcessController candidate = this.processMap.get(pid);
|
this.lockMap.put(pid, false);
|
||||||
if (candidate == null) {
|
|
||||||
JobServServer.logger.write("Tried to release lock of process that doesnt exist!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
candidate.releaseLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,18 @@ class ProcessManagerTestImplementation extends ProcessManager {
|
||||||
|
|
||||||
super.releaseLock(pid);
|
super.releaseLock(pid);
|
||||||
|
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
System.err.println("[!!] Long Call wasnt able to grab lock!");
|
||||||
|
return;
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
super.releaseLock(pid); // this doesnt happen, dont cancel this task
|
super.releaseLock(pid); // this doesnt happen, dont cancel this task
|
||||||
System.err.println("[3] Released lock: interrupted");
|
System.err.println("[3] Released lock: interrupted");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean reportLockState(int pid) {
|
||||||
|
return super.lockMap.get(pid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue