• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gflags/gflags.h>
18 #include <android-base/logging.h>
19 
20 #include <chrono>
21 #include <fstream>
22 #include <iomanip>
23 #include <sstream>
24 
25 #include "common/libs/fs/shared_fd.h"
26 #include "common/libs/utils/flag_parser.h"
27 #include "common/libs/utils/shared_fd_flag.h"
28 #include "host/libs/config/logging.h"
29 
30 namespace cuttlefish {
31 
32 static uint num_tombstones_in_last_second = 0;
33 static std::string last_tombstone_name = "";
34 
next_tombstone_path(const std::string & tombstone_dir)35 static std::string next_tombstone_path(const std::string& tombstone_dir) {
36   auto in_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
37   std::stringstream ss;
38   ss << tombstone_dir << "/tombstone_"
39      << std::put_time(std::gmtime(&in_time_t), "%Y-%m-%d-%H%M%S");
40   auto retval = ss.str();
41 
42   // Gives tombstones unique names
43   if(retval == last_tombstone_name) {
44     num_tombstones_in_last_second++;
45     retval += "_" + std::to_string(num_tombstones_in_last_second);
46   } else {
47     last_tombstone_name = retval;
48     num_tombstones_in_last_second = 0;
49   }
50 
51   LOG(DEBUG) << "Creating " << retval;
52   return retval;
53 }
54 
55 static constexpr size_t CHUNK_RECV_MAX_LEN = 1024;
56 
TombstoneReceiverMain(int argc,char ** argv)57 int TombstoneReceiverMain(int argc, char** argv) {
58   DefaultSubprocessLogging(argv);
59 
60   std::vector<Flag> flags;
61 
62   std::string tombstone_dir;
63   flags.emplace_back(GflagsCompatFlag("tombstone_dir", tombstone_dir)
64                          .Help("directory to write out tombstones in"));
65 
66   SharedFD server_fd;
67   flags.emplace_back(
68       SharedFDFlag("server_fd", server_fd)
69           .Help("File descriptor to an already created vsock server"));
70 
71   flags.emplace_back(HelpFlag(flags));
72   flags.emplace_back(UnexpectedArgumentGuard());
73 
74   std::vector<std::string> args =
75       ArgsToVec(argc - 1, argv + 1);  // Skip argv[0]
76   CHECK(ParseFlags(flags, args)) << "Could not process command line flags.";
77 
78   CHECK(server_fd->IsOpen()) << "Did not receive a server fd";
79 
80   LOG(DEBUG) << "Host is starting server on port "
81              << server_fd->VsockServerPort();
82 
83   // Server loop
84   while (true) {
85     auto conn = SharedFD::Accept(*server_fd);
86     std::ofstream file(next_tombstone_path(tombstone_dir),
87                        std::ofstream::out | std::ofstream::binary);
88 
89     while (file.is_open()) {
90       char buff[CHUNK_RECV_MAX_LEN];
91       auto bytes_read = conn->Read(buff, sizeof(buff));
92       if (bytes_read <= 0) {
93         // reset the other side if it's still connected
94         break;
95       } else {
96         file.write(buff, bytes_read);
97       }
98     }
99   }
100 
101   return 0;
102 }
103 
104 }  // namespace cuttlefish
105 
main(int argc,char ** argv)106 int main(int argc, char** argv) {
107   return cuttlefish::TombstoneReceiverMain(argc, argv);
108 }
109