1959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/* 2959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Copyright (C) 2014 The Android Open Source Project 3959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 4959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Licensed under the Apache License, Version 2.0 (the "License"); 5959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * you may not use this file except in compliance with the License. 6959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * You may obtain a copy of the License at 7959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 8959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * http://www.apache.org/licenses/LICENSE-2.0 9959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 10959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Unless required by applicable law or agreed to in writing, software 11959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * distributed under the License is distributed on an "AS IS" BASIS, 12959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * See the License for the specific language governing permissions and 14959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * limitations under the License. 15959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 16959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 17959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepackage dexfuzz; 18959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 19959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.BufferedReader; 20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.InputStream; 21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.InputStreamReader; 22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.IOException; 23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.ArrayList; 24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.List; 25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.concurrent.Semaphore; 26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/** 28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * process.waitFor() can block if its output buffers are not drained. 29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * These threads are used to keep the buffers drained, and provide the final 30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * output once the command has finished executing. Each Executor has its own 31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * output and error StreamConsumers. 32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class StreamConsumer extends Thread { 34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private List<String> output; 35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private BufferedReader reader; 36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private State state; 38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private Semaphore workToBeDone; 40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private Semaphore outputIsReady; 41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle enum State { 43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle WAITING, 44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle CONSUMING, 45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle SHOULD_STOP_CONSUMING, 46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle FINISHED, 47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle ERROR 48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Create a StreamConsumer, will be immediately ready to start consuming. 52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public StreamConsumer() { 54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle output = new ArrayList<String>(); 55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle workToBeDone = new Semaphore(0); 56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle outputIsReady = new Semaphore(0); 57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle state = State.WAITING; 59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Executor should call this to provide its StreamConsumers with the Streams 63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * for a Process it is about to call waitFor() on. 64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void giveStreamAndStartConsuming(InputStream stream) { 66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle output.clear(); 67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle reader = new BufferedReader(new InputStreamReader(stream)); 69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle changeState(State.CONSUMING, State.WAITING); 71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Tell consumer there is work to be done. 73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle workToBeDone.release(); 74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Executor should call this once its call to waitFor() returns. 78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void processFinished() { 80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle changeState(State.SHOULD_STOP_CONSUMING, State.CONSUMING); 81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Executor should call this to get the captured output of this StreamConsumer. 85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<String> getOutput() { 87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle try { 89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Wait until the output is ready. 90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle outputIsReady.acquire(); 91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } catch (InterruptedException e) { 92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Client of StreamConsumer was interrupted while waiting for output?"); 93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return null; 94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Take a copy of the Strings, so when we call output.clear(), we don't 97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // clear the ExecutionResult's list. 98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle List<String> copy = new ArrayList<String>(output); 99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return copy; 100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Executor should call this when we're shutting down. 104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void shutdown() { 106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle changeState(State.FINISHED, State.WAITING); 107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Tell Consumer there is work to be done (it will check first if FINISHED has been set.) 109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle workToBeDone.release(); 110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private void consume() { 113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle try { 114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (checkState(State.SHOULD_STOP_CONSUMING)) { 116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Caller already called processFinished() before we even started 117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // consuming. Just get what we can and finish. 118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (reader.ready()) { 119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle output.add(reader.readLine()); 120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Caller's process is still executing, so just loop and consume. 123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (checkState(State.CONSUMING)) { 124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Thread.sleep(50); 125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (reader.ready()) { 126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle output.add(reader.readLine()); 127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (checkState(State.SHOULD_STOP_CONSUMING)) { 132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle changeState(State.WAITING, State.SHOULD_STOP_CONSUMING); 133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("StreamConsumer stopped consuming, but was not told to?"); 135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle setErrorState(); 136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle reader.close(); 139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } catch (IOException e) { 141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("StreamConsumer caught IOException while consuming"); 142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle setErrorState(); 143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } catch (InterruptedException e) { 144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("StreamConsumer caught InterruptedException while consuming"); 145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle setErrorState(); 146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Tell client of Consumer that the output is ready. 149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle outputIsReady.release(); 150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void run() { 154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (checkState(State.WAITING)) { 155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle try { 156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Wait until there is work to be done 157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle workToBeDone.acquire(); 158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } catch (InterruptedException e) { 159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("StreamConsumer caught InterruptedException while waiting for work"); 160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle setErrorState(); 161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Check first if we're done 165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (checkState(State.FINISHED)) { 166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Make sure we're either supposed to be consuming 170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // or supposed to be finishing up consuming 171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (!(checkState(State.CONSUMING) || checkState(State.SHOULD_STOP_CONSUMING))) { 172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("invalid state: StreamConsumer told about work, but not CONSUMING?"); 173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("state was: " + getCurrentState()); 174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle setErrorState(); 175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle consume(); 179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private synchronized boolean checkState(State expectedState) { 183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return (expectedState == state); 184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private synchronized void changeState(State newState, State previousState) { 187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (state != previousState) { 188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("StreamConsumer Unexpected state: " + state + ", expected " + previousState); 189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle state = State.ERROR; 190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle state = newState; 192959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 193959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 194959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 195959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private synchronized void setErrorState() { 196959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle state = State.ERROR; 197959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 198959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 199959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private synchronized State getCurrentState() { 200959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return state; 201959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 202959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle} 203