Ive PTRACE_ATTACH and PCONT to a process. Ive also verified the process is still attached, and thats running, yet I cant PTRACE_DETACH (errno : No such process). Im puzzled after doing all the validations. It all happens in void DETACH().
My understanding is that PTRACE_CONT doesnt detach from the process so I should still be able to detach properly. If its not detaching then it means its not attaching properly. but from my validations its attached. I PTRACE_CONT bc I want my tracee program to continue moving(otherwise the image freezes) and remain attached.
Edit: It seems like the problem is that Im trying to detach in another function, PTRACE_DETACH works but if I add this after PTRACE_CONT.
kill(targetPid, SIGSTOP);
waitpid(targetPid, nullptr, 0);
if (ptrace(PTRACE_DETACH, targetPid, nullptr, nullptr) == -1) {
wxLogError("Failed to detach from process: %s", strerror(errno));
} else {
wxLogMessage("Successfully detached from process %d", targetPid);
isAttached = false;
wxThreadEvent *event = new wxThreadEvent(wxEVT_THREAD, EVT_DETACH_SUCCESS);
event->SetString("Successfully detached from process " + std::to_string(targetPid));
wxQueueEvent(m_parent, event);
}
#include <wx/wx.h>
#include <wx/thread.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <string>
#include <dirent.h>
#include <libgen.h>
#include <fcntl.h>
#include <signal.h> // Add this include at the top of your file
#include <fstream>
// Define new event types
wxDEFINE_EVENT(EVT_ATTACH_SUCCESS, wxThreadEvent);
wxDEFINE_EVENT(EVT_DETACH_SUCCESS, wxThreadEvent);
class WorkerThread : public wxThread {
public:
WorkerThread(wxEvtHandler *parent) : wxThread(wxTHREAD_JOINABLE), m_parent(parent), targetPid(-1), isAttached(false) {}
~WorkerThread() override {
if (IsRunning()) {
Detach();
}
}
wxThread::ExitCode Entry() override {
std::string processName = "dura";
int pipefd[2];
if (pipe(pipefd) == -1) {
wxLogError("pipe failed: %s", strerror(errno));
return (wxThread::ExitCode)0;
}
pid_t childPid = fork();
if (childPid == -1) {
wxLogError("fork failed: %s", strerror(errno));
return (wxThread::ExitCode)0;
}
if (childPid == 0) { // Child process
close(pipefd[0]); // Close read end
dup2(pipefd[1], STDOUT_FILENO); // Redirect stdout to pipe
execlp("pgrep", "pgrep", processName.c_str(), nullptr);
wxLogError("execlp failed: %s", strerror(errno));
exit(EXIT_FAILURE);
} else { // Parent process
close(pipefd[1]); // Close write end
int status;
waitpid(childPid, &status, 0);
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { // Process found
char buf[32];
read(pipefd[0], buf, sizeof(buf) - 1);
targetPid = strtoul(buf, nullptr, 10);
if (ptrace(PTRACE_ATTACH, targetPid, nullptr, nullptr) == -1) {
wxLogError("Failed to attach to process: %s", strerror(errno));
return (wxThread::ExitCode)0;
} else {
this->targetPid = targetPid;
isAttached = true;;
wxLogMessage("Successfully attached to process %ld", targetPid);
wxThreadEvent* event = new wxThreadEvent(wxEVT_THREAD, EVT_ATTACH_SUCCESS);
event->SetString("Successfully attached to process " + std::to_string(targetPid));
wxQueueEvent(m_parent, event);
}
// Check if the process is still alive after attaching
if (isAttached && targetPid != -1 && kill(targetPid, 0) == 0) {
wxLogMessage("Process is still alive after attaching.");
} else {
wxLogError("Failed to attach properly or process does not exist.");
return (wxThread::ExitCode)0;
}
//Wait for the process to stop
waitpid(targetPid, nullptr, 0);
// Continue the process
if (ptrace(PTRACE_CONT, targetPid, nullptr, nullptr) == -1) {
wxLogError("Failed to continue the process: %s", strerror(errno));
}
// Wait for the process to stop again after continuing
waitpid(targetPid, nullptr, 0);
while(!TestDestroy()) {
wxThread::This()->Sleep(1000); // 1 second sleep
}
} else if (WIFEXITED(status)) { // Process not found or error executing pgrep
wxLogError("Process %s not found or error executing pgrep.", processName.c_str());
}
}
while(!TestDestroy()) {
wxThread::This()->Sleep(1000); // 1 second sleep
}
return (wxThread::ExitCode)0;
}
void Detach() {
if (isAttached && targetPid != -1) {
int result = kill(targetPid, 0);
if (result == 0) {
// Process is still alive, check if it is attached
if (ptrace(PTRACE_ATTACH, targetPid, nullptr, nullptr) == -1 && errno == ESRCH) {
// Process is not attached, no need to detach
wxLogMessage("Process %ld is not attached", targetPid);
isAttached = false;
} else {
// Process is attached, proceed with detachment
if (ptrace(PTRACE_DETACH, targetPid, nullptr, nullptr) == -1) {
wxLogError("Failed to detach from process: %s", strerror(errno));
} else {
wxLogMessage("Successfully detached from process %ld", targetPid);
isAttached = false;
}
}
} else if (result == -1) {
// Process is not alive
wxLogError("Process %ld is not alive", targetPid);
}
} else {
wxLogError("Failed to detach from process: No such process");
}
}
private:
wxEvtHandler *m_parent;
pid_t targetPid;
bool isAttached;
};
class MyFrame : public wxFrame {
public:
MyFrame() : wxFrame(NULL, wxID_ANY, "Hello wxWidgets") {
m_panel = new wxPanel(this);
m_attachBtn = new wxButton(m_panel, wxID_ANY, "Attach");
m_detachBtn = new wxButton(m_panel, wxID_ANY, "Detach");
m_textCtrl = new wxTextCtrl(m_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxTE_READONLY);
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(m_attachBtn, 0, wxEXPAND | wxALL, 5);
sizer->Add(m_detachBtn, 0, wxEXPAND | wxALL, 5);
sizer->Add(m_textCtrl, 1, wxEXPAND | wxALL, 5);
m_panel->SetSizer(sizer);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnAttach, this, m_attachBtn->GetId());
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnDetach, this, m_detachBtn->GetId());
Bind(EVT_ATTACH_SUCCESS, &MyFrame::OnAttachSuccess, this);
Bind(EVT_DETACH_SUCCESS, &MyFrame::OnDetachSuccess, this);
m_workerThread = nullptr;
}
void OnAttach(wxCommandEvent &event) {
m_workerThread = new WorkerThread(this);
if (m_workerThread->Run() != wxTHREAD_NO_ERROR) {
wxLogError("Could not create the worker thread!");
delete m_workerThread;
m_workerThread = nullptr;
}
m_textCtrl->AppendText("Attaching to process...\n");
}
void OnDetach(wxCommandEvent &event) {
if (m_workerThread) {
m_workerThread->Detach(); // Detach from process
m_workerThread->Delete(); // Signals the thread to exit its main loop
m_workerThread->Wait(); // Waits for the thread to exit
delete m_workerThread;
m_workerThread = nullptr;
}
}
void OnAttachSuccess(wxThreadEvent &event) {
m_textCtrl->AppendText(event.GetString() + "\n");
}
void OnDetachSuccess(wxThreadEvent &event) {
m_textCtrl->AppendText("Successfully detached from process.\n");
}
private:
wxPanel *m_panel;
wxButton *m_attachBtn;
wxButton *m_detachBtn;
wxTextCtrl *m_textCtrl;
WorkerThread *m_workerThread;
};
class MyApp : public wxApp {
public:
bool OnInit() override {
MyFrame *frame = new MyFrame();
frame->Show();
return true;
}
};
wxIMPLEMENT_APP(MyApp);