Fork child process terminates with signal 0 - c

I have a small function that should give me information about how a child process finished.
int debug_wait() {
int status;
wait(&status);
if (WIFSIGNALED(status)) {
int sig = WSTOPSIG(status);
printf("failed with signal %d (%s)\n", sig, strsignal(sig));
return 1;
}
else if (!WIFEXITED(status)) {
printf("ended in an unexpected way\n");
return 1;
}
return 0;
}
But I get the following result:
double free or corruption (out)
tests failed with signal 0 (Unknown signal 0)
I know I should fix my code, but why do I get signal no. 0? Is there a mistake in my function or does it have an other meaning?
Since people asked, here is a example program:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int debug_wait() {
int status;
wait(&status);
if (WIFSIGNALED(status)) {
int sig = WSTOPSIG(status);
printf("tests failed with signal %d (%s)\n", sig, strsignal(sig));
return 1;
}
else if (!WIFEXITED(status)) {
printf("tests ended in an unexpected way\n");
return 1;
}
return 0;
}
int main() {
void* ptr = malloc(10);
pid_t pid = fork();
if (pid == 0) {
free(ptr);
free(ptr);
}
else {
debug_wait();
}
}

You are decoding the wrong thing. If WIFSIGNALED is true you can use WTERMSIG and WCOREDUMP (check #ifdef WCOREDUMP first). To decude the WSTOPSIG then WIFSTOPPED must be true.
Example:
int status;
pid_t pid = wait(&status);
if (pid == -1) return 1;
if (WIFEXITED(status)) {
printf("normal exit %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("termsig %d core dump=%c\n", WTERMSIG(status),
WCOREDUMP(status) ? 'Y' : 'N');
} else if (WIFSTOPPED(status)) {
printf("stop %d cont=%c\n", WSTOPSIG(status),
WIFCONTINUED(status) ? 'Y' : 'N');
}
Without using the feature test macros:
if (WIFEXITED(status)) {
printf("normal exit %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("termsig %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stop %d\n", WSTOPSIG(status));
}

Related

For some reason im getting wrong result using fork

The program creates a child proccess and the child does the proper work in order to see if its pid is even or odd
And for some reason even if the pid is even i get that it is odd , also the parent waits for child
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
pid_t pid, mypid, cpid;
int flag;
pid = getpid();
printf("Process %d creates new process\n\n", pid);
cpid = fork();
if (cpid == 0) {
cpid=getpid();
printf("\n----[%d] child\n", cpid);
if (cpid % 2 == 0) {
flag = 1;
} else {
flag = 0;
}
exit(0);
} else if (cpid != 0) {
wait(NULL);
mypid = getpid();
printf("\n[%d] parent of [%d]\n", mypid, cpid);
if (flag == 1) {
printf("\nThe child pid is even");
} else if(flag ==0) {
printf("\nThe child pid is odd");
} else {
printf("\nSomething went wrong");
}
} else {
perror("Fork failed");
}
return 0;
}

C exiting a program correctly

Hello I am writing a c program which runs then waits for it to complete then executes an if condition. However after the child process completes it does not execute the rest of code in parent. Any advice would be great. Thanks
AA
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
int main() {
int D, waitVal3, waitVal4;
D = fork();
if(D == 0)
{
execv("DD", 0);
}
if(D != 0)
{
printf("\nPid = %d Code AA: created proccess Pid = %d (code DD)\n", getpid(), D);
}
waitVal3 = (waitVal4);
//NEVER ENTERS THIS CONDITION
printf("WAIT VAL: %d", waitVal3);
if(waitVal3 == D)
{
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
DD
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main (int argc, char *argBB[]) {
int C3, waitVal, waitVal2, ps;
C3 = fork();
if(C3 != 0)
{
printf("\nPid = %d Code DD: created proccess Pid = %d (code CC)\n", getpid(), C3);
}
if( C3 == 0 )
{
execv("CC", 0);
printf("\nexecv failed\n");
exit(0);
}
if(C3 < 0)
{
printf("Fork failed");
exit(1);
}
ps = fork();
if(ps != 0)
{
printf("\nPid = %d Code DD: created proccess Pid = %d (code ps)\n", getpid(), ps);
}
if( ps == 0 )
{
char command[50];
strcpy(command, "ps -u username");
system(command);
exit(11);
kill(ps, SIGKILL);//KILL PROCCESS PS HERE
}
waitVal = wait(waitVal2);
if(waitVal == ps)
{
printf("\nPid= %d Code DD: process Pid = %d terminated\n", getpid(), ps);
printf("\nPid = %d Code DD: killing process Pid = %d\n", getpid(), C3);
kill(C3, SIGKILL);
printf("\nPid= %d Code DD: process Pid = %d terminated\n", getpid(), C3);
printf("\nPid = %d Code DD: terminating\n", getpid());
exit(7);
}
return 0;
}
You didn't call wait() and your execv() was incorrect...
... compare this with your version to check the differences...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
int main() {
char *args[2] = {"DD", NULL};
int D, waitVal3, waitVal4, rc, waitStatus;
D = fork();
if ( D == -1 )
{
printf("fork failed\n");
exit(1);
}
if(D == 0)
{
// ORIG: execv("DD", args);
rc = execv("/some/path/to/DD", args);
printf("execv failed: errno: %d\n", errno);
exit(1);
}
if(D != 0)
{
printf("\nPid = %d Code AA: created proccess Pid = %d (code DD)\n", getpid(), D);
}
waitVal4 = wait(&waitStatus);
waitVal3 = (waitVal4);
//ORIGINALLY - NEVER ENTERS THIS CONDITION
printf("WAIT VAL: %d", waitVal3);
if(waitVal3 == D)
{
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
I tried to come up with a solution using waitpid() instead of wait().
Why this didn't work?
int main() {
char *args[2] = {"DD", NULL};
int waitVal3, waitVal4, rc, waitStatus;
pid_t D;
D = fork();
if ( D == -1 )
{
printf("fork failed\n");
exit(1);
}
if(D == 0)
{
// ORIG: execv("DD", args);
if( execv("/home/ubuntu/workspace/C/DD", args) == -1 ){
printf("execv failed: errno: %d\n", errno);
exit(1);
}
if( waitpid( D, &waitStatus, 0 ) == -1 ){
printf("Error waiting child process.\n");
exit(1);
};
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
Observation:
If I put the waitid() statement outside the child process, this works.
The following code worked:
if(D == 0)
{
// ORIG: execv("DD", args);
if( execv("/home/ubuntu/workspace/C/DD", args) == -1 ){
printf("execv failed: errno: %d\n", errno);
exit(1);
}
}
if( waitpid( D, &waitStatus, 0 ) == -1 ){
printf("Error waiting child process.\n");
exit(1);
};
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
This means that the parent process was able detect the termination of child process in this case. My understanding is that waitpid() should work whether
in child or parent process. I am firm believer that it did work. However, the consequent printf() statement in the child process didn't get executed since the child process got terminated.

Execvp doesn't return an error on an unknown command

I have the following code that forks a child and executes the command "a", which is an unknown command. However, execvp does not return an error and instead, "success" is printed. The same thing happens if I do "mv a b", when the file "a" does not exist. How should I capture and handle these errors?
int main ( int argc, char **argv ){
pid_t pid;
char *execArgs[] = { "a", NULL };
pid = fork();
// if fork fails
if (pid < 0){
exit(EXIT_FAILURE);
}
else if (pid == 0){
execvp(execArgs[0], execArgs);
if (errno == ENOENT)
_exit(-1);
_exit(-2);
}
else{
int status;
wait(&status);
if(!WIFEXITED(status)){
printf("error\n");
}
else{
printf("success\n");
}
}
}
The program exited; it just exited with a non-zero status. The primary opposite of WIFEXITED is WIFSIGNALED — see the POSIX specification for wait() and WIFSTOPPED and WIFCONTINUED for the other options.
Use:
int corpse = wait(&status);
if (corpse != -1 && WIFEXITED(status))
{
int estat = WEXITSTATUS(status);
char *err = (estat == 0) ? "success" : "failure";
printf("PID %d exited with status %d (%s)\n", corpse, estat, err);
}
else
printf("PID %d didn't exit; it was signalled\n", corpse);

Function that returns exit type as string

I want my program to output how the process has exited, as seen in the second line after the user's prompt and input.
shell> wait
shell: process has exited abnormally with signal 11: Segmentation fault.
What function would I use in my printf()? I thought of exit() but that returns void. Could it be strsignal, if so, what would I pass as the int for strsignal? Thank you!
You are correct, it is strsignal(). See this example: https://www.cs.fsu.edu/~baker/opsys/examples/forkexec/print_child_status.c
Relevant portion:
#include <stdio.h>
#include <wait.h>
#include <string.h>
void print_child_status (int status) {
if (WIFEXITED (status)) {
fprintf (stdout, "Child exited with status %d\n", WEXITSTATUS (status));
} else if (WIFSTOPPED (status)) {
fprintf (stdout, "Child stopped by signal %d (%s)\n", WSTOPSIG (status), strsignal (WSTOPSIG (status)));
} else if (WIFSIGNALED (status)) {
fprintf (stdout, "Child killed by signal %d (%s)\n", WTERMSIG (status), strsignal (WTERMSIG (status)));
} else {
fprintf (stdout, "Unknown child status\n");
}
}
You can refer to the code at towards the end in the following link http://linux.die.net/man/2/waitpid
The demonstration of the program:
$ ./a.out &
Child PID is 32360
[1] 32359
$ kill -STOP 32360
stopped by signal 19
$ kill -CONT 32360
continued
$ kill -TERM 32360
killed by signal 15
[1]+ Done ./a.out
$
Source of the program:
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
pid_t cpid, w;
int status;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Code executed by child */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Wait for signals */
_exit(atoi(argv[1]));
} else { /* Code executed by parent */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
}

Ptrace/wait on a non child

int Enable ( int pid)
{
int status;
#if 1
{
printf ( "child pid = %d \n", pid );
long ret = ptrace (PTRACE_ATTACH, pid, NULL, NULL);
do {
int w = waitpid(-1, &status, 0);
if (w == -1) {
perror("waitpid error :");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
#endif
// while ((result = wait(&status)) != -1 && result != pid){ printf (" this is not my child go back \n"); };
}
int main(int arg, char*argv[])
{
Enable(atoi(argv[1]));
sleep(125);
}
-- I ran a daemon with pid 6841 and tried to wait on it after ptrace-attach
./ptrace 6841
child pid = 6841
waitpid error :: No child processes
In short I want to be able to wait on a non-child process - any other program welcome.
oops. not working if Iam not root :)
This is documented behavior; see ptrace() - Unix, Linux System Call e. g.
non-root processes cannot trace processes that they cannot send
signals to
if(ret == 0)
{
//child process
}
else
{
//parent process
}

Resources