dumpsys.cpp revision 159a8323064d8550218bf31465e51cc5a5d14926
1f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/*
2f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * Command that dumps interesting system state to the log.
3f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *
4f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross */
5f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
6f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#define LOG_TAG "dumpsys"
7f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
84b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <algorithm>
94b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <chrono>
104b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <thread>
114b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
124b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <android-base/file.h>
134b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <android-base/unique_fd.h>
144b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <binder/IServiceManager.h>
15f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <binder/Parcel.h>
16f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <binder/ProcessState.h>
17002e1e58dfe19dd3e49a59c6827cbf51573941a2Mathias Agopian#include <binder/TextOutput.h>
184b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <utils/Log.h>
19f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <utils/Vector.h>
20f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
214b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <fcntl.h>
22f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <getopt.h>
23f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <stdio.h>
244b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <stdlib.h>
25f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <string.h>
264b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <sys/poll.h>
274b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <sys/socket.h>
28f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/time.h>
294b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <sys/types.h>
304b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao#include <unistd.h>
31f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
32f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossusing namespace android;
334b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gaousing android::base::unique_fd;
344b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gaousing android::base::WriteFully;
35f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
36f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic int sort_func(const String16* lhs, const String16* rhs)
37f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross{
38f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return lhs->compare(*rhs);
39f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
40f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
41bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Lemestatic void usage() {
42bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme    fprintf(stderr,
43bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme        "usage: dumpsys\n"
44bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme            "         To dump all services.\n"
45bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme            "or:\n"
468b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            "       dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
47bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme            "         --help: shows this help\n"
48bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme            "         -l: only list services, do not dump them\n"
498b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            "         -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
50859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme            "         --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
51859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme            "         SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
52859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme}
53859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme
54859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Lemebool IsSkipped(const Vector<String16>& skipped, const String16& service) {
55859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme    for (const auto& candidate : skipped) {
56859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme        if (candidate == service) {
57859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme            return true;
58859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme        }
59859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme    }
60859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme    return false;
61bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme}
62bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme
63f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossint main(int argc, char* const argv[])
64f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross{
653e03d3fb6a4cb93f5f978f9d2eed7b7cc62a06a6JP Abgrall    signal(SIGPIPE, SIG_IGN);
66f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    sp<IServiceManager> sm = defaultServiceManager();
67f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    fflush(stdout);
68f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (sm == NULL) {
69bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme        ALOGE("Unable to get default service manager!");
70f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        aerr << "dumpsys: Unable to get default service manager!" << endl;
71f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        return 20;
72f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
73f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
74f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    Vector<String16> services;
75f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    Vector<String16> args;
76859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme    Vector<String16> skippedServices;
77caad555f3efaf77941c4eacd4f6c84eb22d14f6dkeunyoung    bool showListOnly = false;
788b78b758a8b5b831c48562233df055c22e2541afThierry Strudel    bool skipServices = false;
798b78b758a8b5b831c48562233df055c22e2541afThierry Strudel    int timeoutArg = 10;
808b78b758a8b5b831c48562233df055c22e2541afThierry Strudel    static struct option longOptions[] = {
818b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        {"skip", no_argument, 0,  0 },
828b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        {"help", no_argument, 0,  0 },
838b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        {     0,           0, 0,  0 }
848b78b758a8b5b831c48562233df055c22e2541afThierry Strudel    };
858b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
868b78b758a8b5b831c48562233df055c22e2541afThierry Strudel    while (1) {
878b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        int c;
888b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        int optionIndex = 0;
898b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
908b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        c = getopt_long(argc, argv, "+t:l", longOptions, &optionIndex);
918b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
928b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        if (c == -1) {
938b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            break;
94bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme        }
958b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
968b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        switch (c) {
978b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        case 0:
988b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            if (!strcmp(longOptions[optionIndex].name, "skip")) {
998b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                skipServices = true;
1008b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            } else if (!strcmp(longOptions[optionIndex].name, "help")) {
1018b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                usage();
1028b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                return 0;
1038b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            }
1048b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            break;
1058b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
1068b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        case 't':
1078b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            {
1088b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                char *endptr;
1098b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                timeoutArg = strtol(optarg, &endptr, 10);
1108b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                if (*endptr != '\0' || timeoutArg <= 0) {
1118b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                    fprintf(stderr, "Error: invalid timeout number: '%s'\n", optarg);
1128b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                    return -1;
1138b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                }
1148b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            }
1158b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            break;
1168b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
1178b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        case 'l':
118bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme            showListOnly = true;
1198b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            break;
1208b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
1218b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        default:
1228b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            fprintf(stderr, "\n");
1238b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            usage();
1248b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            return -1;
125bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme        }
126caad555f3efaf77941c4eacd4f6c84eb22d14f6dkeunyoung    }
1278b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
1288b78b758a8b5b831c48562233df055c22e2541afThierry Strudel    for (int i = optind; i < argc; i++) {
1298b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        if (skipServices) {
1308b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            skippedServices.add(String16(argv[i]));
1318b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        } else {
1328b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            if (i == optind) {
1338b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                services.add(String16(argv[i]));
1348b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            } else {
1358b78b758a8b5b831c48562233df055c22e2541afThierry Strudel                args.add(String16(argv[i]));
136859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme            }
137859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme        }
138859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme    }
1398b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
1408b78b758a8b5b831c48562233df055c22e2541afThierry Strudel    if ((skipServices && skippedServices.empty()) ||
1418b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            (showListOnly && (!services.empty() || !skippedServices.empty()))) {
1428b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        usage();
1438b78b758a8b5b831c48562233df055c22e2541afThierry Strudel        return -1;
1448b78b758a8b5b831c48562233df055c22e2541afThierry Strudel    }
1458b78b758a8b5b831c48562233df055c22e2541afThierry Strudel
146159a8323064d8550218bf31465e51cc5a5d14926Thierry Strudel    if (services.empty() || showListOnly) {
147859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme        // gets all services
148f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        services = sm->listServices();
149f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        services.sort(sort_func);
150f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        args.add(String16("-a"));
151f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
152f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
153f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    const size_t N = services.size();
154f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
155f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (N > 1) {
156f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        // first print a list of the current services
157f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        aout << "Currently running services:" << endl;
158bbfd2b89434e57cb0720d59383b5bf5339492028Felipe Leme
159f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        for (size_t i=0; i<N; i++) {
160f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            sp<IBinder> service = sm->checkService(services[i]);
161f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            if (service != NULL) {
162859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme                bool skipped = IsSkipped(skippedServices, services[i]);
163859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme                aout << "  " << services[i] << (skipped ? " (skipped)" : "") << endl;
164f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            }
165f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
166f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
167f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
168caad555f3efaf77941c4eacd4f6c84eb22d14f6dkeunyoung    if (showListOnly) {
169caad555f3efaf77941c4eacd4f6c84eb22d14f6dkeunyoung        return 0;
170caad555f3efaf77941c4eacd4f6c84eb22d14f6dkeunyoung    }
171caad555f3efaf77941c4eacd4f6c84eb22d14f6dkeunyoung
1724b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao    for (size_t i = 0; i < N; i++) {
1734b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao        String16 service_name = std::move(services[i]);
1744b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao        if (IsSkipped(skippedServices, service_name)) continue;
175859aef6a32ba03aae8e487078deb469a3ff84e6bFelipe Leme
1764b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao        sp<IBinder> service = sm->checkService(service_name);
177f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        if (service != NULL) {
1784b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            int sfd[2];
1794b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
18049f0a0cddbcad9be1d408425ee608ca925c6885bJosh Gao            if (pipe(sfd) != 0) {
18149f0a0cddbcad9be1d408425ee608ca925c6885bJosh Gao                aerr << "Failed to create pipe to dump service info for " << service_name
1824b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                     << ": " << strerror(errno) << endl;
1834b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                continue;
1844b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            }
1854b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
1864b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            unique_fd local_end(sfd[0]);
1874b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            unique_fd remote_end(sfd[1]);
1884b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            sfd[0] = sfd[1] = -1;
1894b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
190f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            if (N > 1) {
191f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                aout << "------------------------------------------------------------"
192f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                        "-------------------" << endl;
1934b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                aout << "DUMP OF SERVICE " << service_name << ":" << endl;
194f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            }
1954b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
1964b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            // dump blocks until completion, so spawn a thread..
1974b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            std::thread dump_thread([=, remote_end { std::move(remote_end) }]() mutable {
1984b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                int err = service->dump(remote_end.get(), args);
1994b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2004b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                // It'd be nice to be able to close the remote end of the socketpair before the dump
2014b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                // call returns, to terminate our reads if the other end closes their copy of the
2024b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                // file descriptor, but then hangs for some reason. There doesn't seem to be a good
2034b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                // way to do this, though.
2044b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                remote_end.clear();
2054b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2064b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                if (err != 0) {
2074b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    aerr << "Error dumping service info: (" << strerror(err) << ") " << service_name
2084b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                         << endl;
2094b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                }
2104b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            });
2114b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2128b78b758a8b5b831c48562233df055c22e2541afThierry Strudel            auto timeout = std::chrono::seconds(timeoutArg);
2134b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            auto end = std::chrono::steady_clock::now() + timeout;
2144b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2154b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            struct pollfd pfd = {
2164b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                .fd = local_end.get(),
2174b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                .events = POLLIN
2184b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            };
2194b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2204b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            bool timed_out = false;
2214b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            bool error = false;
2224b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            while (true) {
2234b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                // Wrap this in a lambda so that TEMP_FAILURE_RETRY recalculates the timeout.
2244b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                auto time_left_ms = [end]() {
2254b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    auto now = std::chrono::steady_clock::now();
2264b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
2274b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    return std::max(diff.count(), 0ll);
2284b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                };
2294b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2304b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
2314b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                if (rc < 0) {
2324b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    aerr << "Error in poll while dumping service " << service_name << " : "
2334b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                         << strerror(errno) << endl;
2344b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    error = true;
2354b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    break;
2364b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                } else if (rc == 0) {
2374b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    timed_out = true;
2384b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    break;
2394b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                }
2404b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2414b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                char buf[4096];
2424b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                rc = TEMP_FAILURE_RETRY(read(local_end.get(), buf, sizeof(buf)));
2434b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                if (rc < 0) {
2444b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    aerr << "Failed to read while dumping service " << service_name << ": "
2454b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                         << strerror(errno) << endl;
2464b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    error = true;
2474b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    break;
2484b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                } else if (rc == 0) {
2494b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    // EOF.
2504b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    break;
2514b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                }
2524b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2534b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                if (!WriteFully(STDOUT_FILENO, buf, rc)) {
2544b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    aerr << "Failed to write while dumping service " << service_name << ": "
2554b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                         << strerror(errno) << endl;
2564b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    error = true;
2574b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                    break;
2584b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                }
2594b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            }
2604b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2614b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            if (timed_out) {
2624b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                aout << endl << "*** SERVICE DUMP TIMEOUT EXPIRED ***" << endl << endl;
2634b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            }
2644b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao
2654b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            if (timed_out || error) {
2664b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                dump_thread.detach();
2674b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            } else {
2684b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao                dump_thread.join();
269f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            }
270f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        } else {
2714b8f6f9adb8ee1a06b145c8dc83a672f8d0ac80fJosh Gao            aerr << "Can't find service: " << service_name << endl;
272f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
273f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
274f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
275f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return 0;
276f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
277