completely different approach to attach/detach on linux

develop
Petr Mrázek 2009-10-31 18:09:13 +00:00
parent 879834178d
commit 78ec035f02
4 changed files with 63 additions and 14 deletions

@ -677,13 +677,12 @@ void DFHackAPIImpl::FinishReadCreatures()
bool DFHackAPIImpl::Attach() bool DFHackAPIImpl::Attach()
{ {
// detach all processes, destroy manager // detach all processes, destroy manager
if(pm != NULL) if(pm == NULL)
delete pm; pm = new ProcessManager(xml); // FIXME: handle bad XML better
// find a process (ProcessManager can find multiple when used properly) // find a process (ProcessManager can find multiple when used properly)
pm = new ProcessManager(xml); // FIXME: handle bad XML better
if(!pm->findProcessess()) if(!pm->findProcessess())
return false; // FIXME: throw exceptions to distinguish errors? provide error code? return false;
p = (*pm)[0]; // we just use the first found process p = (*pm)[0];
if(!p->attach()) if(!p->attach())
return false; // couldn't attach to process, no go return false; // couldn't attach to process, no go
offset_descriptor = p->getDescriptor(); offset_descriptor = p->getDescriptor();

@ -72,31 +72,74 @@ void Process::setMemFile(const string & memf)
memFile = memf; memFile = memf;
} }
#ifdef LINUX_BUILD #ifdef LINUX_BUILD
/* /*
* LINUX PART * LINUX PART
*/ */
//TODO: rewrite this. really. It's ugly as hell.
bool isStopped(pid_t pid)
{
char filename[256];
sprintf(filename, "/proc/%d/status", pid);
// evil mess, that's a fitting name for this thing
FILE* evil = fopen(filename,"rb");
if(evil)
{
// zlo means evil in czech.
char zlo[256];
char zlo2[256];
char test;
// read first line, ignore
fgets(zlo,256,evil);
// read second line
fgets(zlo,256,evil);
sscanf(zlo,"State: %c %s",&test, zlo2 );
fclose(evil);
if(test == 'T')
{
string crap = zlo2;
if(crap == "(stopped)")
{
return true;
}
}
return false;
}
cerr << "couldn't open file " << filename << "assuming process stopped" << endl;
return true;
}
// shamelessly stolen from dwarf therapist code. credit should go to the author there :) // shamelessly stolen from dwarf therapist code. credit should go to the author there :)
bool Process::attach() bool Process::attach()
{ {
int status;
cout << "Attach: start" << endl;
// check if another process is attached // check if another process is attached
if(g_pProcess != NULL) if(g_pProcess != NULL)
{ {
return false; return false;
} }
cout << "Attach_start" << endl; if(!isStopped(my_handle))
{
kill(my_handle,SIGSTOP);
while (!isStopped(my_handle));
}
cout << "Attach: after conditional stop" << endl;
// can we attach? // can we attach?
if (ptrace(PTRACE_ATTACH , my_handle, NULL, NULL) == -1) if (ptrace(PTRACE_ATTACH , my_handle, NULL, NULL) == -1)
{ {
// no, we got an error // no, we got an error
perror("ptrace attach error"); perror("ptrace attach error");
cerr << "attach failed on pid" << my_handle << endl; cerr << "attach failed on pid " << my_handle << endl;
return false; return false;
} }
cout << "Attach_after_ptrace" << endl;
int status; cout << "Attach: after ptrace" << endl;
/*
while(true) while(true)
{ {
// we wait on the pid // we wait on the pid
@ -114,8 +157,8 @@ bool Process::attach()
{ {
break; break;
} }
} }*/
cout << "Managed to attach to pid " << my_handle << endl; // cout << "Managed to attach to pid " << my_handle << endl;
int proc_pid_mem = open(memFile.c_str(),O_RDONLY); int proc_pid_mem = open(memFile.c_str(),O_RDONLY);
if(proc_pid_mem == -1) if(proc_pid_mem == -1)
@ -132,7 +175,7 @@ bool Process::attach()
g_ProcessHandle = my_handle; g_ProcessHandle = my_handle;
g_ProcessMemFile = proc_pid_mem; g_ProcessMemFile = proc_pid_mem;
cout << "Attach_after_opening /proc/PID/mem" << endl; cout << "Attach: after opening /proc/"<< my_handle <<"/mem" << endl;
return true; // we are attached return true; // we are attached
} }
} }
@ -161,10 +204,14 @@ bool Process::detach()
} }
else else
{ {
cout << "detach: after detaching from "<< my_handle << endl; // cout << "detach: after detaching from "<< my_handle << endl;
attached = false; attached = false;
g_pProcess = NULL; g_pProcess = NULL;
g_ProcessHandle = 0; g_ProcessHandle = 0;
// continue, wait for it to recover
kill(my_handle,SIGCONT);
while (isStopped(my_handle));
// we finish
return true; return true;
} }
} }

@ -48,5 +48,7 @@ int main (void)
} }
} }
delete pDF; delete pDF;
cout << "Done. Press any key to continue" << endl;
cin.ignore();
return 0; return 0;
} }

@ -110,6 +110,7 @@ int main (void)
cout << endl << endl; cout << endl << endl;
} }
DF.FinishReadCreatures(); DF.FinishReadCreatures();
DF.Detach();
delete pDF; delete pDF;
cout << "Done. Press any key to continue" << endl; cout << "Done. Press any key to continue" << endl;
cin.ignore(); cin.ignore();