How to use ptrace() to observe process until it exits? - c

I am looking for a ptrace() call to observe a process until the process exits.
I have this which compiles with gcc / cc on OSX:
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sys/ptrace.h>
int main(int argc, char *argv[]) {
pid_t pidx = atoi(argv[1]);
printf("pid = %jd\n", (intmax_t) pidx);
ptrace(PT_ATTACHEXC, pidx, 0, 0);
wait(NULL);
}
However, even with a valid/existing pid, this program will still exit immediately. I am trying to only exit this program after pidx dies.
Is this possible somehow?
Ideally I want something that works on both OSX and Linux.

Your problem is probably that the wait call returns immediately, because the traced "inferior" process is suspended, you know, waiting for you to debug it. You're going to need some kind of loop in which you make ptrace requests to inspect the child and then resume execution, and then call wait again to wait for it to suspend on the next breakpoint or whatever. Unfortunately the debugger API is extremely non-portable; you will have to write most of this program twice, once for OSX and once for Linux.

Related

execl in C programming

I have a C program. I noticed that you can't put 2 execl's in it.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t fork(void);
int system(const char *command);
execl("/bin/sh", "sh", "-c", "kdialog --warningcontinuecancel
\"Make sure to include: \n \n 1. py_lcd folder \n 2. 4x20
Raspberry Pi LCD Display \n 3. Python 2.7.12 to be installed \n
\n If you are missing something, kill the program process and
get them.\"", (char *) 0);
sleep(1);
execl("/bin/sh", "sh", "-c", "kdialog --msgbox \"Setting up files...\" --title \"Installing...\"", (char *) 0);
return(0);
}
Can someone help me if there is a way to bypass this or if i am making a mistake???
The exec family of functions don't return when they succeed. They replace the running process with the one being execed. If you want to run a program in a child process (with full control, unlike system), you need to use fork + exec + wait (or perhaps posix_spawn).
Anything written after execl is a deadcode. The main purpose of execl is to re-use the current process information for a new process to improve performance. You will be using sharing the same structures of process information(pid, stack, heap etc.) of the current process where execl is executed.
I found an answer myself. There is a system() command which works the exact same but you are able to insert it anywhere in the code without problems

setpgid(0, 0) fails when debugging with gdb

I'm trying to debug a linux user-space application, which creates a process group with setpgid(0,0). When launched on terminal, it returns no error and work as expected. But when debugging with gdb, it returns EPERM.
I suspect that it is because the gdb attaches my process as a child. So it is not possible to set my process as parent with setpgid(0,0). Is that correct? If so, isn't there a way to debug this case with gdb?
Edit:
Environment:
Ubuntu 12.04 Kernel 3.11.0-15-generic
Using the simple code below, if launched on terminal, I get success!!. If I debug with gdb (configured on Eclipse Luna), I get setpgid: Operation not permitted.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int err = setpgid((pid_t)0, (pid_t) 0);
if (err < 0)
perror("setpgid");
else
printf("success!! \n");
exit(err);
}

Buffering `printf` outputs between different threads in Linux

Here is my code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
pthread_t ntid;void
printids(const char *s) {
printf("%s \n", s);
}
void *
thr_fn(void *arg) {
printids("new thread: ");
return((void *)0);
}
int
main(void) {
pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
}
I'm running it on Red Hat Enterprise Linux Workstation release 6.5 .
Here is my compiling command
gcc -ansi -g -std=c99 -Wall -DLINUX -D_GNU_SOURCE threadid.c -o threadid -pthread -lrt -lbsd
Here is the output:
main thread:
new thread:
new thread:
Why "new thread" has been printed twice?
I doubt this may related to buffering mechanism in Linux. But after I added fflush(stdout) and fsync(1) in the end of each function. The output is almost the same.
If you run the program several times. The output differs:
main thread:
new thread:
or
main thread:
new thread:
new thread:
Or
main thread:
Most libc libraries do buffer the output as you mentioned. And at the end of the program (when the main thread exits), they flush all the buffers and exit.
There is a slight possibility that your new thread has flushed the output but before it could update the state of the buffer, the main program exited and the cleanup code flushed the same buffer again. Since these buffers are local to the thread I am sure they won't have concurrency mechanism. But because of this rare case it might get messed up.
You can try
err = pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
pthread_join(ntid, NULL);
At the end of the main function and check if the problem is solved.
This will cause your main function to wait till the new thread is finished (including the flushing operation it does).
Double output is possible on glibc-based linux systems due to a nasty bug in glibc: if the FILE lock is already held at the time exit tries to flush, the lock is simply ignored and the buffer access is performed with no synchronization. This would be a great test case to report to glibc to pressure them to fix it, if you can reproduce it reliably.

System call for a core dump?

i have a question:
exists any system call for generate a core dump?
I know which a core dump could be generated by a signal, but i want know if it's possible generated from system call
void createdump(void)
{
if(!fork()) { //child process
// Crash the app
abort() || (*((void*)0) = 42);
}
}
What ever place you wan't to dump call the function. This will create a child and crash it. So you can get dump even without exiting your program
You can also raise the SIGABRT signal to get the core dump.
raise(SIGABRT);
*this is equivalent to calling abort() directly.
Same idea as code hacker's answer, but compilable, with error handling, and without the zombie:
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int
coredump(void)
{
pid_t p,r;
if(0>(p=fork()))
return -1;
if(0==p)
abort() /*child*/;
/*reap zombie*/
do r=waitpid(p,0,0); while(0>r && EINTR==errno);
if(0>r) {
perror("waitpid shouldn't have failed");
abort();
}
return 0;
}
This still has the rather obvious deficiency in that that it won't work with multithreaded processes.

c daemon() for unix doesnt work with sleep()

I have very simple code that should run on background and at 1 am shut down the computer:
#include <ctime>
#include <cstdlib>
#include <unistd.h>
int main() {
time_t t;struct tm * now;
daemon(0,0);
while(1){
t = time(0);
now = localtime( & t );
if(now->tm_hour==1){
system("shutdown -P");
break;
}
sleep(10);
}
return 0;
}
The code works without sleep(10) but uses whole free memory so I need sleep function there to stop loop and recheck time each ten seconds, but with sleep function program stops immediately after I run it.
If you are writing C code, don't use C++ headers (ctime, cstdlib). Replace those #includes with #include <stdlib.h> and #include <time.h>. If the behavior of this code is really as you describe (which I would find surprising), then this is probably the source of the error.
Of course it immediately exits. Thats the whole point of using daemon. Check with ps and you will see that your proram is still running as a seperate process now.
Check the man page for a desription how daemon works.

Resources