setpgid(0, 0) fails when debugging with gdb - c

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);
}

Related

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

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.

Unclear issue with fork(), possibly with source file?

I'm a beginner programmer to C and I'm trying to write a basic shell. I'm trying to use the fork() function, but it simply doesn't seem to work. I get caught in an endless loop of just my shell's prompt taking input and then seemingly doing nothing with it.
I ran the debugger and set the breakpoint to where the program forks, and at that point, I got an error message of
Can't find a source file at "/build/glibc-Cl5G7W/glibc-2.23/posix/../sysdeps/nptl/fork.c"
Locate the file or edit the source lookup path to include its location.
What I think is happening is that I either messed up with my #include headers or that when I tried to compile, I left some library out. I've just been compiling with the standard
gcc -o shell custom_shell.c
and I recall my teacher saying something about compiling with libraries, but I thought my #include headers would cover that and I can't find anything else on the topic online.
The parts of my code I'm wary over are
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
...
pid_t pid = fork();
if (pid < 0){ //error
perror("fork");
exit(1);
}
else if (pid == 0){ //child
execvp(args[0], args);
}
else{ //parent
wait(0);
}

How to generate a core dump without crashing down a process in c?

Is it possible to generate a mini core dump for debugging purpose without crashing the process. Let's say if a function receives an unexpected value, just printing logs and returning gracefully might not be sufficient to debug the issue. On the other hand, if i can get a screenshot of memory and look at the stack, i could find more useful information to debug.
Yes,
According to gdb's documentation, once attached with gdb you may issue the following command:
(gdb) gcore
(gdb) q
This will dump the core to "core.pid" without crashing the process.
or this one-liner:
sudo sh -c 'echo gcore <output_core> | gdb -p <pid>'
There is not building function to do that, you could use ptrace() to debug your own process but it would not be easy. Call gcore is the easiest method.
#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/wait.h>
int main(void) {
pid_t parent = getpid();
pid_t pid = fork();
if (pid < 0) {
// oh dear we are on trouble
} else if (pid == 0) {
char tmp[42];
snprintf(tmp, sizeof tmp, "%" PRIdMAX, (intmax_t)parent);
execvp("gcore", (char *[]){"gcore", tmp, NULL});
} else {
int wstatus;
waitpid(pid, &wstatus, 0);
}
}

Windows Linux compatibility layer. Function not implemented?

ORIGINAL:
I've been trying to implement a basic shared memory program using the Windows Subsystem for Linux (aka Bash on Ubuntu on Windows). Here is the code I wrote:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define KEY 1374
int shmid;
char *dataPtr;
int main (void) {
shmid = shmget((key_t)KEY,1024, IPC_CREAT | 0666);
dataPtr = shmat(shmid, (void*)0,0);
if(dataPtr == (char*)(-1))
perror("shmat error");
strcpy(dataPtr,"test");
sleep(10);
shmdt(dataPtr);
shmctl(shmid, IPC_RMID, NULL);
}
I compiled it with GCC without any error or warning, but when I tried to run it, I got this error message:
shmat error: Function not implemented
Segmentation fault (core dumped)
I tried to get to the bottom of this error, but when I googled it, I
literally got nothing.
So the question is: did I horribly messed-up something very simple, or is it possible that the shared-memory system isn't implemented on "Ubuntu on Windows"?
EDIT:
I tried to run my code on my faculty's linux server, and it worked fine. So apparently the problem is with the Bash on Ubuntu on Windows system. The shared-memory system probably isn't implemented at all.

Unable to identify behaviour of execl() function call

I was working on my project when I needed to use "curl" to obtain some data from www. Now firstly I tried direct system() function but it didn't worked, strangely everytime it corrupted the whole source code file while compiling with gcc. Luckily I was testing it separately.
Then I tested execl() function, this code compiles OK and gcc gives me a .exe file to run, but nothing happens when I run it,blank windows appears. CODE:
int main(){
execl("curl","curl","http://livechat.rediff.com/sports/score/score.txt",">blahblah.txt",NULL);
getch();
return 0;
}
Includes are not shown properly but I have included stdio,conio,stdlib and unistd.h.
How can I get output of program to store in text file? Also running the above command creates and stores text file in My Documents, I want it to be in local directory from where I run the program. How can I do that?
You need to provide the path of curl, and you cannot use redirection because the application will not be executed through bash. Instead use the -o flag and specify the filename. Also, execl does not return when successful:
#include <unistd.h>
#include <stdio.h>
int main(){
execl("/usr/bin/curl",
"curl","http://livechat.rediff.com/sports/score/score.txt",
"-oblahblah.txt",NULL
);
printf("error\n");
return 0;
}
If you want your code to return, you should fork a child process to run the command. This way you can check the return code.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define CURL "/usr/bin/curl"
int main()
{
pid_t pid;
int status;
pid = fork();
if (pid == 0)
{
execl(CURL, CURL, arg1, NULL);
}
else if (pid < 0)
{
printf("Fork failed\n");
exit (1);
}
else
{
if (waitpid(pid, &status, 0) != pid)
status = -1;
}
return status;
}
arg1 is whatever argument you want to use with curl or if you aren't using any than you obviously can omit it.

Resources