1 package shared;
2 
3 import java.lang.management.ManagementFactory;
4 import java.lang.management.OperatingSystemMXBean;
5 import java.util.Arrays;
6 //import com.sun.management.OperatingSystemMXBean;
7 import java.util.concurrent.atomic.AtomicBoolean;
8 import java.util.concurrent.atomic.AtomicIntegerArray;
9 
10 /**
11  * Monitors CPU utilization to determine if the program has crashed.
12  * Also performs VM forced shutdowns and safe memory allocation.
13  * @author Brian Bushnell
14  * @date Feb 25, 2015
15  *
16  */
17 public final class KillSwitch extends Thread {
18 
main(String[] args)19 	public static void main(String[] args){
20 		double seconds=Double.parseDouble(args[0]);
21 		double load=Double.parseDouble(args[1]);
22 		launch(seconds, load);
23 		if(args.length>2){
24 
25 		}
26 	}
27 
KillSwitch(double seconds, double load)28 	private KillSwitch(double seconds, double load) {
29 		maxSeconds=seconds;
30 		minLoad=load;
31 	}
32 
launch()33 	public static boolean launch(){
34 		return launch(600);
35 	}
36 
launch(double seconds)37 	public static boolean launch(double seconds){
38 		return launch(seconds, 0.002);
39 	}
40 
launch(double seconds, double load)41 	public static synchronized boolean launch(double seconds, double load){
42 		if(count>0){return false;}
43 		ks=new KillSwitch(seconds, load);
44 		ks.start();
45 		return true;
46 	}
47 
48 	@Override
run()49 	public void run(){
50 
51 		boolean success=monitor();
52 //		System.err.println("success: "+success);
53 		if(!success || killFlag.get()){
54 			if(!suppressMessages){
55 				System.err.println("Process has decided it has crashed, and will abort.\n" +
56 						"If this decision was incorrect, please re-run with the flag 'monitor=f'");
57 			}
58 			kill0();
59 		}
60 	}
61 
monitor()62 	private boolean monitor(){
63 
64 		final OperatingSystemMXBean bean=ManagementFactory.getOperatingSystemMXBean();
65 		if(bean.getSystemLoadAverage()<0){
66 			System.err.println("This OS does not support monitor, so monitoring was disabled.");
67 			return true;
68 		}
69 
70 		final long start=System.currentTimeMillis();
71 		final long buffer=(long)(1+maxSeconds*1000);
72 		long stop=start+buffer;
73 //		System.err.println("start="+start+", stop="+stop+", buffer="+buffer);
74 //		System.err.println("shutdownFlag.get()="+shutdownFlag.get());
75 		while(!shutdownFlag.get()){
76 			try {
77 				sleep(500);
78 			} catch (InterruptedException e) {
79 				// TODO Auto-generated catch block
80 				e.printStackTrace();
81 			}
82 			final double load=bean.getSystemLoadAverage();
83 			final long time=System.currentTimeMillis();
84 			if(load>minLoad){stop=time+buffer;}
85 			if(time>stop){return false;}
86 //			System.err.println("stop-time="+(stop-time)+", load="+load);
87 		}
88 //		System.err.println("shutdownFlag.get()="+shutdownFlag.get());
89 		return true;
90 	}
91 
92 	/*--------------------------------------------------------------*/
93 
kill(String s)94 	public static synchronized void kill(String s){
95 		ballast=null;
96 		Exception e=new Exception(s);
97 		e.printStackTrace();
98 		kill0();
99 	}
100 
101 //	public static void kill(Throwable e){
102 //		e.printStackTrace();
103 //		kill0();
104 //	}
105 
kill()106 	public static synchronized void kill(){
107 		ballast=null;
108 		Exception e=new Exception("Aborting.");
109 		e.printStackTrace();
110 		kill0();
111 	}
112 
killSilent()113 	public static synchronized void killSilent(){
114 		ballast=null;
115 		kill0();
116 	}
117 
kill0()118 	private static void kill0(){
119 		ballast=null;
120 		Runtime.getRuntime().halt(1);
121 	}
122 
shutdown()123 	public static void shutdown(){
124 		shutdownFlag.set(true);
125 	}
126 
setKillFlag()127 	public static void setKillFlag(){
128 		killFlag.set(true);
129 	}
130 
131 	/*--------------------------------------------------------------*/
132 
throwableKill(Throwable e)133 	public static final void throwableKill(Throwable e){
134 		ballast=null;
135 		synchronized(MemKillMessage){
136 			e.printStackTrace();
137 			kill0();
138 		}
139 	}
140 
exceptionKill(Exception e)141 	public static final void exceptionKill(Exception e){
142 		ballast=null;
143 		synchronized(MemKillMessage){
144 			e.printStackTrace();
145 			kill0();
146 		}
147 	}
148 
memKill(OutOfMemoryError e)149 	public static final void memKill(OutOfMemoryError e){
150 		ballast=null;
151 		synchronized(MemKillMessage){
152 			e.printStackTrace();
153 			System.err.println(MemKillMessage);
154 //			Shared.printMemory();
155 //			killSilent();
156 			kill0();
157 		}
158 	}
159 
assertionKill(AssertionError e)160 	public static final void assertionKill(AssertionError e){
161 		ballast=null;
162 		synchronized(MemKillMessage){
163 //			System.err.println(e);
164 			e.printStackTrace();
165 			kill0();
166 		}
167 	}
168 
169 
170 	/*--------------------------------------------------------------*/
171 
allocAtomicInt(int len)172 	public static final AtomicIntegerArray allocAtomicInt(int len){
173 		AtomicIntegerArray ret=null;
174 		try {
175 			ret=new AtomicIntegerArray(len);
176 		} catch (OutOfMemoryError e) {
177 			memKill(e);
178 		}
179 		return ret;
180 	}
181 
allocLong1D(int len)182 	public static final long[] allocLong1D(int len){
183 		long[] ret=null;
184 		try {
185 			ret=new long[len];
186 		} catch (OutOfMemoryError e) {
187 			memKill(e);
188 		}
189 		return ret;
190 	}
191 
allocInt1D(int len)192 	public static final int[] allocInt1D(int len){
193 		int[] ret=null;
194 		try {
195 			ret=new int[len];
196 		} catch (OutOfMemoryError e) {
197 			memKill(e);
198 		}
199 		return ret;
200 	}
201 
allocFloat1D(int len)202 	public static float[] allocFloat1D(int len) {
203 		float[] ret=null;
204 		try {
205 			ret=new float[len];
206 		} catch (OutOfMemoryError e) {
207 			memKill(e);
208 		}
209 		return ret;
210 	}
211 
allocDouble1D(int len)212 	public static double[] allocDouble1D(int len) {
213 		double[] ret=null;
214 		try {
215 			ret=new double[len];
216 		} catch (OutOfMemoryError e) {
217 			memKill(e);
218 		}
219 		return ret;
220 	}
221 
allocByte1D(int len)222 	public static final byte[] allocByte1D(int len){
223 		byte[] ret=null;
224 		try {
225 			ret=new byte[len];
226 		} catch (OutOfMemoryError e) {
227 			memKill(e);
228 		}
229 		return ret;
230 	}
231 
allocChar1D(int len)232 	public static final char[] allocChar1D(int len){
233 		char[] ret=null;
234 		try {
235 			ret=new char[len];
236 		} catch (OutOfMemoryError e) {
237 			memKill(e);
238 		}
239 		return ret;
240 	}
241 
242 	/*--------------------------------------------------------------*/
243 
allocInt2D(int x)244 	public static final int[][] allocInt2D(int x){
245 		int[][] ret=null;
246 		try {
247 			ret=new int[x][];
248 		} catch (OutOfMemoryError e) {
249 			memKill(e);
250 		}
251 		return ret;
252 	}
253 
allocInt2D(int x, int y)254 	public static final int[][] allocInt2D(int x, int y){
255 		int[][] ret=null;
256 		try {
257 			ret=new int[x][y];
258 		} catch (OutOfMemoryError e) {
259 			ballast2=null;
260 			System.err.print(x+","+y);
261 			memKill(e);
262 		}
263 		return ret;
264 	}
265 
allocFloat2D(int x)266 	public static final float[][] allocFloat2D(int x){
267 		float[][] ret=null;
268 		try {
269 			ret=new float[x][];
270 		} catch (OutOfMemoryError e) {
271 			memKill(e);
272 		}
273 		return ret;
274 	}
275 
allocFloat2D(int x, int y)276 	public static final float[][] allocFloat2D(int x, int y){
277 		float[][] ret=null;
278 		try {
279 			ret=new float[x][y];
280 		} catch (OutOfMemoryError e) {
281 			ballast2=null;
282 			System.err.print(x+","+y);
283 			memKill(e);
284 		}
285 		return ret;
286 	}
287 
allocLong2D(int x)288 	public static final long[][] allocLong2D(int x){
289 		long[][] ret=null;
290 		try {
291 			ret=new long[x][];
292 		} catch (OutOfMemoryError e) {
293 			memKill(e);
294 		}
295 		return ret;
296 	}
297 
allocLong2D(int x, int y)298 	public static final long[][] allocLong2D(int x, int y){
299 		long[][] ret=null;
300 		try {
301 			ret=new long[x][y];
302 		} catch (OutOfMemoryError e) {
303 			memKill(e);
304 		}
305 		return ret;
306 	}
307 
308 	/*--------------------------------------------------------------*/
309 
allocInt3D(int x)310 	public static int[][][] allocInt3D(int x) {
311 		int[][][] ret=null;
312 		try {
313 			ret=new int[x][][];
314 		} catch (OutOfMemoryError e) {
315 			memKill(e);
316 		}
317 		return ret;
318 	}
319 
allocInt3D(int x, int y)320 	public static int[][][] allocInt3D(int x, int y) {
321 		int[][][] ret=null;
322 		try {
323 			ret=new int[x][y][];
324 		} catch (OutOfMemoryError e) {
325 			memKill(e);
326 		}
327 		return ret;
328 	}
329 
allocInt3D(int x, int y, int z)330 	public static int[][][] allocInt3D(int x, int y, int z) {
331 		int[][][] ret=null;
332 		try {
333 			ret=new int[x][y][z];
334 		} catch (OutOfMemoryError e) {
335 			memKill(e);
336 		}
337 		return ret;
338 	}
339 
340 	/*--------------------------------------------------------------*/
341 
copyOf(byte[] buffer, long newLength)342 	public static byte[] copyOf(byte[] buffer, long newLength) {
343 		final int len=buffer.length;
344 		final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN);
345 		if(newLength>len2 && len2<=len){
346 			exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength));
347 		}
348 		byte[] copy=null;
349 		try {
350 			copy=Arrays.copyOf(buffer, len2);
351 		} catch (OutOfMemoryError e) {
352 			memKill(e);
353 		}
354 		return copy;
355 	}
356 
copyOf(float[] buffer, long newLength)357 	public static float[] copyOf(float[] buffer, long newLength) {
358 		final int len=buffer.length;
359 		final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN);
360 		if(newLength>len2 && len2<=len){
361 			exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength));
362 		}
363 		float[] copy=null;
364 		try {
365 			copy=Arrays.copyOf(buffer, len2);
366 		} catch (OutOfMemoryError e) {
367 			memKill(e);
368 		}
369 		return copy;
370 	}
371 
copyOf(double[] buffer, long newLength)372 	public static double[] copyOf(double[] buffer, long newLength) {
373 		final int len=buffer.length;
374 		final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN);
375 		if(newLength>len2 && len2<=len){
376 			exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength));
377 		}
378 		double[] copy=null;
379 		try {
380 			copy=Arrays.copyOf(buffer, len2);
381 		} catch (OutOfMemoryError e) {
382 			memKill(e);
383 		}
384 		return copy;
385 	}
386 
387 	/**
388 	 * Copy the buffer into an array of size newLength.
389 	 * Fill extra cells with fillValue.
390 	 * @param buffer Old array
391 	 * @param newLength Length of new array
392 	 * @param fillValue Value to insert in extra cells
393 	 * @return New array
394 	 */
copyAndFill(int[] buffer, long newLength, int fillValue)395 	public static int[] copyAndFill(int[] buffer, long newLength, int fillValue) {
396 		final int[] copy=copyOf(buffer, newLength);
397 		Arrays.fill(copy, buffer.length, copy.length, fillValue);
398 		return copy;
399 	}
400 
copyOf(int[] buffer, long newLength)401 	public static int[] copyOf(int[] buffer, long newLength) {
402 		final int len=buffer.length;
403 		final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN);
404 		if(newLength>len2 && len2<=len){
405 			exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength));
406 		}
407 		int[] copy=null;
408 		try {
409 			copy=Arrays.copyOf(buffer, len2);
410 		} catch (OutOfMemoryError e) {
411 			memKill(e);
412 		}
413 		return copy;
414 	}
415 
copyOf(int[][] buffer, long newLength)416 	public static int[][] copyOf(int[][] buffer, long newLength) {
417 		final int len=buffer.length;
418 		final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN);
419 		if(newLength>len2 && len2<=len){
420 			exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength));
421 		}
422 		int[][] copy=null;
423 		try {
424 			copy=Arrays.copyOf(buffer, len2);
425 		} catch (OutOfMemoryError e) {
426 			memKill(e);
427 		}
428 		return copy;
429 	}
430 
copyOf(long[] buffer, long newLength)431 	public static long[] copyOf(long[] buffer, long newLength) {
432 		final int len=buffer.length;
433 		final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN);
434 		if(newLength>len2 && len2<=len){
435 			exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength));
436 		}
437 		long[] copy=null;
438 		try {
439 			copy=Arrays.copyOf(buffer, len2);
440 		} catch (OutOfMemoryError e) {
441 			memKill(e);
442 		}
443 		return copy;
444 	}
445 
copyAndFill(long[] buffer, long newLength, int fillValue)446 	public static long[] copyAndFill(long[] buffer, long newLength, int fillValue) {
447 		final long[] copy=copyOf(buffer, newLength);
448 		Arrays.fill(copy, buffer.length, copy.length, fillValue);
449 		return copy;
450 	}
451 
copyOf(long[][] buffer, long newLength)452 	public static long[][] copyOf(long[][] buffer, long newLength) {
453 		final int len=buffer.length;
454 		final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN);
455 		if(newLength>len2 && len2<=len){
456 			exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength));
457 		}
458 		long[][] copy=null;
459 		try {
460 			copy=Arrays.copyOf(buffer, len2);
461 		} catch (OutOfMemoryError e) {
462 			memKill(e);
463 		}
464 		return copy;
465 	}
466 
467 	/*--------------------------------------------------------------*/
468 
copyOfRange(byte[] buffer, int from, int to)469 	public static byte[] copyOfRange(byte[] buffer, int from, int to) {
470 		byte[] copy=null;
471 		try {
472 			copy=Arrays.copyOfRange(buffer, from, to);
473 		} catch (OutOfMemoryError e) {
474 			memKill(e);
475 		}
476 		return copy;
477 	}
478 
copyOfRange(int[] buffer, int start, int limit)479 	public static int[] copyOfRange(int[] buffer, int start, int limit) {
480 		int[] copy=null;
481 		try {
482 			copy=Arrays.copyOfRange(buffer, start, limit);
483 		} catch (OutOfMemoryError e) {
484 			memKill(e);
485 		}
486 		return copy;
487 	}
488 
copyOfRange(long[] buffer, int start, int limit)489 	public static long[] copyOfRange(long[] buffer, int start, int limit) {
490 		long[] copy=null;
491 		try {
492 			copy=Arrays.copyOfRange(buffer, start, limit);
493 		} catch (OutOfMemoryError e) {
494 			memKill(e);
495 		}
496 		return copy;
497 	}
498 
499 	/*--------------------------------------------------------------*/
500 
501 	private final double maxSeconds;
502 	private final double minLoad;
503 
504 	private static AtomicBoolean shutdownFlag=new AtomicBoolean(false);
505 	private static AtomicBoolean killFlag=new AtomicBoolean(false);
506 	private static int count=0;
507 	private static KillSwitch ks;
508 	private static boolean suppressMessages=false;
509 
510 	/*--------------------------------------------------------------*/
511 
512 	private static final String MemKillMessage=new String("\nThis program ran out of memory.\n"
513 			+ "Try increasing the -Xmx flag and using tool-specific memory-related parameters.");
514 
addBallast()515 	public static void addBallast() {
516 		synchronized(KillSwitch.class){
517 			ballast=new int[20000];
518 			ballast2=new int[20000];
519 			ballast[0]=1;
520 			assert(ballast[0]==1);
521 		}
522 	}
523 
524 	private static int[] ballast;
525 	private static int[] ballast2;
526 
527 }
528