| 1054 | |
| 1055 | |
| 1056 | void MemoryProfiler::stopAndGenerateRawProfile() |
| 1057 | { |
| 1058 | ASSERT(detectJemalloc()); |
| 1059 | |
| 1060 | VLOG(1) << "Attempting to stop current profiling run"; |
| 1061 | |
| 1062 | // If there is no current profiling run, there is nothing to do. |
| 1063 | if (!currentRun.isSome()) { |
| 1064 | return; |
| 1065 | } |
| 1066 | |
| 1067 | Try<bool> stopped = jemalloc::stopProfiling(); |
| 1068 | |
| 1069 | if (stopped.isError()) { |
| 1070 | LOG(WARNING) << "Failed to stop memory profiling: " << stopped.error(); |
| 1071 | |
| 1072 | // Don't give up. Probably it will fail again in the future, but at least |
| 1073 | // the problem will be clearly visible in the logs. |
| 1074 | currentRun->extend(this, Seconds(5)); |
| 1075 | |
| 1076 | return; |
| 1077 | } |
| 1078 | |
| 1079 | // Heap profiling should not be active any more. |
| 1080 | // We won't retry stopping and generating a profile after this point: |
| 1081 | // We're not actively sampling any more, and if the user still cares |
| 1082 | // about this profile they will get the data with the next run. |
| 1083 | Try<bool> stillActive = jemalloc::profilingActive(); |
| 1084 | CHECK(stillActive.isError() || !stillActive.get()); |
| 1085 | |
| 1086 | time_t runId = currentRun->id; |
| 1087 | Clock::cancel(currentRun->timer); |
| 1088 | currentRun = None(); |
| 1089 | |
| 1090 | if (!stopped.get()) { |
| 1091 | // This is a weird state to end up in, apparently something else in this |
| 1092 | // process stopped profiling independently of us. |
| 1093 | // If there was some valuable, un-dumped data it is still possible to get |
| 1094 | // it by starting a new run. |
| 1095 | LOG(WARNING) |
| 1096 | << "Memory profiling unexpectedly inactive; not dumping profile. Ensure" |
| 1097 | << " nothing else is interfacing with jemalloc in this process"; |
| 1098 | return; |
| 1099 | } |
| 1100 | |
| 1101 | // We store the new artifact even in case of error to surface it to the user. |
| 1102 | rawProfile = DiskArtifact::create( |
| 1103 | RAW_PROFILE_FILENAME, |
| 1104 | runId, |
| 1105 | [](const string& outputPath) -> Try<Nothing> { |
| 1106 | // Make sure we actually have permissions to write to the file and that |
| 1107 | // there is at least a little bit space left on the device. |
| 1108 | const string data(DUMMY_FILE_SIZE, '\0'); |
| 1109 | Try<Nothing> written = os::write(outputPath, data); |
| 1110 | if (written.isError()) { |
| 1111 | return Error(written.error()); |
| 1112 | } |
| 1113 |
nothing calls this directly
no test coverage detected