+// Should be close to createFile() (src/track/libheaptrack.cpp) code,
+// since we could route output from heaptrack to heaptrack_interpret via pipe
+// and use heaptrack's output configuration environment variables directly.
+// Note, should provide only stdout/stderr/socket/file output stream support.
+outStream* createStream(const char* fileName)
+{
+ string outputFileName;
+ if (fileName) {
+ outputFileName.assign(fileName);
+ }
+
+ if (outputFileName == "-" || outputFileName == "stdout") {
+ fprintf(stderr, "will write to stdout");
+ return OpenStream<outStreamFILE, FILE*>(stdout);
+ } else if (outputFileName == "stderr") {
+ fprintf(stderr, "will write to stderr");
+ return OpenStream<outStreamFILE, FILE*>(stderr);
+ } else if (outputFileName == "socket") {
+ uint16_t Port = outStreamSOCKET::DefaultSocketPort;
+ char *env = nullptr;
+ env = getenv("DUMP_HEAPTRACK_SOCKET");
+ if (env) {
+ try {
+ int tmpPort = std::stoi(std::string(env));
+ if (tmpPort < outStreamSOCKET::MinAllowedSocketPort
+ || tmpPort > outStreamSOCKET::MaxAllowedSocketPort) {
+ fprintf(stderr, "WARNING: DUMP_HEAPTRACK_SOCKET socket port is out of allowed range.\n");
+ throw std::out_of_range("DUMP_HEAPTRACK_SOCKET socket port is out of allowed range");
+ }
+ Port = static_cast<uint16_t>(tmpPort);
+ } catch (...) {
+ // do nothing, use default port
+ fprintf(stderr,
+ "WARNING: DUMP_HEAPTRACK_SOCKET should be number in %i-%i range\n",
+ outStreamSOCKET::MinAllowedSocketPort,
+ outStreamSOCKET::MaxAllowedSocketPort);
+ fprintf(stderr, "WARNING: switched to default port %i\n",
+ static_cast<int>(outStreamSOCKET::DefaultSocketPort));
+ }
+ unsetenv("DUMP_HEAPTRACK_SOCKET");
+ }
+
+ outStream *tmpStream = OpenStream<outStreamSOCKET, uint16_t>(Port);
+
+ env = getenv("DUMP_HEAPTRACK_SOCKET_PROMPT");
+ if (env) {
+ if (fprintf(tmpStream, "%s\n", env) < 0
+ || !tmpStream->Flush()) {
+ fprintf(stderr, "WARNING: can't send socket prompt \"%s\".\n", env);
+ }
+ unsetenv("DUMP_HEAPTRACK_SOCKET_PROMPT");
+ }
+
+ fprintf(stderr, "will write to socket/%p\n", tmpStream);
+ return tmpStream;
+ }
+
+ if (outputFileName.empty()) {
+ // env var might not be set when linked directly into an executable
+ outputFileName = "heaptrack.$$";
+ }
+
+ boost::replace_all(outputFileName, "$$", to_string(getpid()));
+
+ auto out = OpenStream<outStreamFILE, const char*>(outputFileName.c_str());
+ fprintf(stderr, "will write to %s/%p\n", outputFileName.c_str(), out);
+ return out;
+}
+