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