bugreport.cpp revision 9b73bf07d73dbab5b792632e1e233edbad77f5fd
19b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris/*
29b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * Copyright (C) 2009 The Android Open Source Project
39b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris *
49b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License");
59b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * you may not use this file except in compliance with the License.
69b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * You may obtain a copy of the License at
79b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris *
89b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris *      http://www.apache.org/licenses/LICENSE-2.0
99b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris *
109b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * Unless required by applicable law or agreed to in writing, software
119b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS,
129b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * See the License for the specific language governing permissions and
149b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * limitations under the License.
159b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris */
169b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
179b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <errno.h>
189b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <stdio.h>
199b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <sys/socket.h>
209b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <sys/types.h>
219b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <unistd.h>
229b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
239b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <cutils/properties.h>
249b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <cutils/sockets.h>
259b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
269b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris// This program will trigger the dumpstate service to start a call to
279b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris// dumpstate, then connect to the dumpstate local client to read the
289b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris// output. All of the dumpstate output is written to stdout, including
299b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris// any errors encountered while reading/writing the output.
309b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferrisint main() {
319b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // Start the dumpstate service.
329b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  property_set("ctl.start", "dumpstate");
339b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
349b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // Socket will not be available until service starts.
359b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  int s;
369b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  for (int i = 0; i < 20; i++) {
379b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED,
389b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris                            SOCK_STREAM);
399b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    if (s >= 0)
409b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      break;
419b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    // Try again in 1 second.
429b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    sleep(1);
439b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  }
449b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
459b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  if (s == -1) {
469b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    printf("Failed to connect to dumpstate service: %s\n", strerror(errno));
479b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    return 1;
489b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  }
499b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
509b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // Set a timeout so that if nothing is read in 3 minutes, we'll stop
519b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // reading and quit. No timeout in dumpstate is longer than 60 seconds,
529b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // so this gives lots of leeway in case of unforeseen time outs.
539b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  struct timeval tv;
549b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  tv.tv_sec = 3 * 60;
559b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  tv.tv_usec = 0;
569b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
579b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno));
589b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  }
599b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
609b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  while (1) {
619b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    char buffer[65536];
629b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer)));
639b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    if (bytes_read == 0) {
649b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      break;
659b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    } else if (bytes_read == -1) {
669b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      // EAGAIN really means time out, so change the errno.
679b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      if (errno == EAGAIN) {
689b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris        errno = ETIMEDOUT;
699b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      }
709b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      printf("\nBugreport read terminated abnormally (%s).\n", strerror(errno));
719b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      break;
729b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    }
739b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
749b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    ssize_t bytes_to_send = bytes_read;
759b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    ssize_t bytes_written;
769b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    do {
779b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      bytes_written = TEMP_FAILURE_RETRY(write(STDOUT_FILENO,
789b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris                                               buffer + bytes_read - bytes_to_send,
799b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris                                               bytes_to_send));
809b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      if (bytes_written == -1) {
819b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris        printf("Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
829b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris               bytes_read, bytes_to_send, strerror(errno));
839b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris        return 1;
849b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      }
859b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      bytes_to_send -= bytes_written;
869b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    } while (bytes_written != 0 && bytes_to_send > 0);
879b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  }
889b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
899b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  TEMP_FAILURE_RETRY(close(s));
909b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  return 0;
919b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris}
92