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