@@ -70,60 +70,30 @@ bool PerfRecord::runPerf(bool elevatePrivileges, const QStringList& perfOptions,
7070 m_perfControlFifo.close ();
7171 m_perfRecordProcess->kill ();
7272 }
73- m_perfRecordProcess = std::make_unique<QProcess>(this );
74- m_perfRecordProcess->setProcessChannelMode (QProcess::MergedChannels);
7573
76- const auto outputFileInfo = QFileInfo (outputPath);
77- const auto folderPath = outputFileInfo.dir ().path ();
78- const auto folderInfo = QFileInfo (folderPath);
79- if (!folderInfo.exists ()) {
80- emit recordingFailed (tr (" Folder '%1' does not exist." ).arg (folderPath));
81- return false ;
82- }
83- if (!folderInfo.isDir ()) {
84- emit recordingFailed (tr (" '%1' is not a folder." ).arg (folderPath));
85- return false ;
86- }
87- if (!folderInfo.isWritable ()) {
88- emit recordingFailed (tr (" Folder '%1' is not writable." ).arg (folderPath));
89- return false ;
90- }
91-
92- connect (m_perfRecordProcess.get (), static_cast <void (QProcess::*)(int , QProcess::ExitStatus)>(&QProcess::finished),
93- this , [this ](int exitCode, QProcess::ExitStatus exitStatus) {
94- Q_UNUSED (exitStatus)
74+ m_outputPath = outputPath;
75+ m_userTerminated = false ;
9576
96- const auto outputFileInfo = QFileInfo (m_outputPath);
97- if ((exitCode == EXIT_SUCCESS || (exitCode == SIGTERM && m_userTerminated) || outputFileInfo.size () > 0 )
98- && outputFileInfo.exists ()) {
99- if (exitCode != EXIT_SUCCESS && !m_userTerminated) {
100- emit debuggeeCrashed ();
101- }
102- emit recordingFinished (m_outputPath);
103- } else {
104- emit recordingFailed (tr (" Failed to record perf data, error code %1." ).arg (exitCode));
105- }
106- m_userTerminated = false ;
107- });
77+ if (m_host->isLocal ()) {
78+ return runPerfLocal (elevatePrivileges, perfOptions, outputPath, workingDirectory);
79+ } else {
80+ return runPerfRemote (perfOptions, outputPath, workingDirectory);
81+ }
82+ }
10883
109- connect (m_perfRecordProcess.get (), &QProcess::errorOccurred, this , [this ](QProcess::ProcessError error) {
110- Q_UNUSED (error)
111- if (!m_userTerminated) {
112- emit recordingFailed (m_perfRecordProcess->errorString ());
113- }
114- });
84+ bool PerfRecord::runPerfLocal (bool elevatePrivileges, const QStringList& perfOptions, const QString& outputPath,
85+ const QString& workingDirectory)
86+ {
87+ m_perfRecordProcess = std::make_unique<QProcess>(this );
88+ m_perfRecordProcess->setProcessChannelMode (QProcess::MergedChannels);
11589
116- connect (m_perfRecordProcess.get (), &QProcess::started, this ,
117- [this ] { emit recordingStarted (m_perfRecordProcess->program (), m_perfRecordProcess->arguments ()); });
90+ connectRecordingProcessErrors ();
11891
11992 connect (m_perfRecordProcess.get (), &QProcess::readyRead, this , [this ]() {
12093 const auto output = QString::fromUtf8 (m_perfRecordProcess->readAll ());
12194 emit recordingOutput (output);
12295 });
12396
124- m_outputPath = outputPath;
125- m_userTerminated = false ;
126-
12797 if (!workingDirectory.isEmpty ()) {
12898 m_perfRecordProcess->setWorkingDirectory (workingDirectory);
12999 }
@@ -160,6 +130,36 @@ bool PerfRecord::runPerf(bool elevatePrivileges, const QStringList& perfOptions,
160130 return true ;
161131}
162132
133+ bool PerfRecord::runPerfRemote (const QStringList& perfOptions, const QString& outputPath,
134+ const QString& workingDirectory)
135+ {
136+ m_perfRecordProcess = m_host->remoteDevice ()->runPerf (workingDirectory, perfOptions);
137+
138+ auto output = new QFile (outputPath, m_perfRecordProcess.get ());
139+ if (!output->open (QIODevice::WriteOnly)) {
140+ emit recordingFailed (QStringLiteral (" Failed to create output file: %1" ).arg (outputPath));
141+ return false ;
142+ }
143+
144+ connect (m_perfRecordProcess.get (), &QProcess::readyReadStandardOutput, m_perfRecordProcess.get (),
145+ [process = m_perfRecordProcess.get (), output] {
146+ auto data = process->readAllStandardOutput ();
147+ output->write (data);
148+ });
149+ connect (m_perfRecordProcess.get (), &QProcess::readyReadStandardError, m_perfRecordProcess.get (),
150+ [this ] { emit recordingOutput (QString::fromUtf8 (m_perfRecordProcess->readAllStandardError ())); });
151+
152+ connect (m_perfRecordProcess.get (), qOverload<int , QProcess::ExitStatus>(&QProcess::finished), this , [output] {
153+ output->close ();
154+ output->deleteLater ();
155+ });
156+
157+ connectRecordingProcessErrors ();
158+
159+ m_perfRecordProcess->start ();
160+ return true ;
161+ }
162+
163163void PerfRecord::record (const QStringList& perfOptions, const QString& outputPath, bool elevatePrivileges,
164164 const QStringList& pids)
165165{
@@ -245,3 +245,33 @@ bool PerfRecord::actuallyElevatePrivileges(bool elevatePrivileges) const
245245 const auto capabilities = m_host->perfCapabilities ();
246246 return elevatePrivileges && capabilities.canElevatePrivileges && !capabilities.privilegesAlreadyElevated ;
247247}
248+
249+ void PerfRecord::connectRecordingProcessErrors ()
250+ {
251+ connect (m_perfRecordProcess.get (), qOverload<int , QProcess::ExitStatus>(&QProcess::finished), this ,
252+ [this ](int exitCode, QProcess::ExitStatus exitStatus) {
253+ Q_UNUSED (exitStatus)
254+
255+ const auto outputFileInfo = QFileInfo (m_outputPath);
256+ if ((exitCode == EXIT_SUCCESS || (exitCode == SIGTERM && m_userTerminated) || outputFileInfo.size () > 0 )
257+ && outputFileInfo.exists ()) {
258+ if (exitCode != EXIT_SUCCESS && !m_userTerminated) {
259+ emit debuggeeCrashed ();
260+ }
261+ emit recordingFinished (m_outputPath);
262+ } else {
263+ emit recordingFailed (tr (" Failed to record perf data, error code %1." ).arg (exitCode));
264+ }
265+ m_userTerminated = false ;
266+ });
267+
268+ connect (m_perfRecordProcess.get (), &QProcess::errorOccurred, this , [this ](QProcess::ProcessError error) {
269+ Q_UNUSED (error)
270+ if (!m_userTerminated) {
271+ emit recordingFailed (m_perfRecordProcess->errorString ());
272+ }
273+ });
274+
275+ connect (m_perfRecordProcess.get (), &QProcess::started, this ,
276+ [this ] { emit recordingStarted (m_perfRecordProcess->program (), m_perfRecordProcess->arguments ()); });
277+ }
0 commit comments