StdioConverter.cpp revision f6c387128427e121477c1b32ad35cdcaa5101ba3
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Thread that reads from stdout/stderr and converts them to log messages.
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Sort of a hack.)
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <fcntl.h>
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kFilenoStdout   1
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kFilenoStderr   2
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Hold our replacement stdout/stderr.
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct StdPipes {
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stdoutPipe[2];
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stderrPipe[2];
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} StdPipes;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kMaxLine    512
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Hold some data.
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct BufferedData {
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char    buf[kMaxLine+1];
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int     count;
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} BufferedData;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// fwd
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* stdioConverterThreadStart(void* arg);
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool readAndLog(int fd, BufferedData* data, const char* tag);
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Crank up the stdout/stderr converter thread.
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns immediately.
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmStdioConverterStartup(void)
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StdPipes* pipeStorage;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.haltStdioConverter = false;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&gDvm.stdioConverterLock);
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_cond_init(&gDvm.stdioConverterCond, NULL);
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pipeStorage = (StdPipes*) malloc(sizeof(StdPipes));
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pipeStorage == NULL)
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pipe(pipeStorage->stdoutPipe) != 0) {
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("pipe failed: %s\n", strerror(errno));
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pipe(pipeStorage->stderrPipe) != 0) {
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("pipe failed: %s\n", strerror(errno));
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dup2(pipeStorage->stdoutPipe[1], kFilenoStdout) != kFilenoStdout) {
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("dup2(1) failed: %s\n", strerror(errno));
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    close(pipeStorage->stdoutPipe[1]);
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pipeStorage->stdoutPipe[1] = -1;
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_ANDROID_OS
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* don't redirect stderr on sim -- logs get written there! */
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* (don't need this on the sim anyway) */
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dup2(pipeStorage->stderrPipe[1], kFilenoStderr) != kFilenoStderr) {
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("dup2(2) failed: %d %s\n", errno, strerror(errno));
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    close(pipeStorage->stderrPipe[1]);
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pipeStorage->stderrPipe[1] = -1;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create the thread.
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.stdioConverterLock);
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmCreateInternalThread(&gDvm.stdioConverterHandle,
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "Stdio Converter", stdioConverterThreadStart, pipeStorage))
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pipeStorage);
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* new thread owns pipeStorage */
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (!gDvm.stdioConverterReady) {
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int cc = pthread_cond_wait(&gDvm.stdioConverterCond,
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    &gDvm.stdioConverterLock);
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(cc == 0);
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.stdioConverterLock);
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shut down the stdio converter thread if it was started.
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since we know the thread is just sitting around waiting for something
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to arrive on stdout, print something.
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmStdioConverterShutdown(void)
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.haltStdioConverter = true;
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.stdioConverterHandle == 0)    // not started, or still starting
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* print something to wake it up */
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Shutting down\n");
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fflush(stdout);
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD("Joining stdio converter...\n");
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_join(gDvm.stdioConverterHandle, NULL);
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Select on stdout/stderr pipes, waiting for activity.
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * DO NOT use printf from here.
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* stdioConverterThreadStart(void* arg)
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define MAX(a,b) ((a) > (b) ? (a) : (b))
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StdPipes* pipeStorage = (StdPipes*) arg;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    BufferedData* stdoutData;
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    BufferedData* stderrData;
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* tell the main thread that we're ready */
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.stdioConverterLock);
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.stdioConverterReady = true;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cc = pthread_cond_signal(&gDvm.stdioConverterCond);
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(cc == 0);
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.stdioConverterLock);
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* we never do anything that affects the rest of the VM */
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(NULL, THREAD_VMWAIT);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate read buffers.
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stdoutData = (BufferedData*) malloc(sizeof(*stdoutData));
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stderrData = (BufferedData*) malloc(sizeof(*stderrData));
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stdoutData->count = stderrData->count = 0;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Read until shutdown time.
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (!gDvm.haltStdioConverter) {
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ssize_t actual;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fd_set readfds;
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int maxFd, fdCount;
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FD_ZERO(&readfds);
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FD_SET(pipeStorage->stdoutPipe[0], &readfds);
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FD_SET(pipeStorage->stderrPipe[0], &readfds);
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        maxFd = MAX(pipeStorage->stdoutPipe[0], pipeStorage->stderrPipe[0]);
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fdCount = select(maxFd+1, &readfds, NULL, NULL, NULL);
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (fdCount < 0) {
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (errno != EINTR) {
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("select on stdout/stderr failed\n");
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGD("Got EINTR, ignoring\n");
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (fdCount == 0) {
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGD("WEIRD: select returned zero\n");
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool err = false;
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (FD_ISSET(pipeStorage->stdoutPipe[0], &readfds)) {
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                err |= !readAndLog(pipeStorage->stdoutPipe[0], stdoutData,
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "stdout");
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (FD_ISSET(pipeStorage->stderrPipe[0], &readfds)) {
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                err |= !readAndLog(pipeStorage->stderrPipe[0], stderrData,
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "stderr");
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* probably EOF; give up */
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (err) {
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("stdio converter got read error; shutting it down\n");
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    close(pipeStorage->stdoutPipe[0]);
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    close(pipeStorage->stderrPipe[0]);
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pipeStorage);
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(stdoutData);
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(stderrData);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* change back for shutdown sequence */
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(NULL, THREAD_RUNNING);
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef MAX
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Data is pending on "fd".  Read as much as will fit in "data", then
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * write out any full lines and compact "data".
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool readAndLog(int fd, BufferedData* data, const char* tag)
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ssize_t actual;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t want;
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(data->count < kMaxLine);
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    want = kMaxLine - data->count;
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actual = read(fd, data->buf + data->count, want);
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (actual <= 0) {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("read %s: (%d,%d) failed (%d): %s\n",
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tag, fd, want, (int)actual, strerror(errno));
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("read %s: %d at %d\n", tag, actual, data->count);
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data->count += actual;
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Got more data, look for an EOL.  We expect LF or CRLF, but will
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * try to handle a standalone CR.
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp = data->buf;
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* start = data->buf;
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i = data->count;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = data->count; i > 0; i--, cp++) {
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '\n' || (*cp == '\r' && i != 0 && *(cp+1) != '\n')) {
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *cp = '\0';
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGW("GOT %d at %d '%s'\n", cp - start, start - data->buf, start);
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG(LOG_INFO, tag, "%s", start);
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            start = cp+1;
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See if we overflowed.  If so, cut it off.
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (start == data->buf && data->count == kMaxLine) {
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data->buf[kMaxLine] = '\0';
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG(LOG_INFO, tag, "%s!", start);
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        start = cp + kMaxLine;
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Update "data" if we consumed some output.  If there's anything left
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the buffer, it's because we didn't see an EOL and need to keep
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * reading until we see one.
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (start != data->buf) {
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (start >= data->buf + data->count) {
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* consumed all available */
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            data->count = 0;
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* some left over */
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int remaining = data->count - (start - data->buf);
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            memmove(data->buf, start, remaining);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            data->count = remaining;
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
293