Cannot compile with waitid() and P_PID - c

I am new to Linux. I am trying to use waitid() to wait for a child process.
When I try to compile a file including the following lines using gcc:
id_t cpid = fork();
siginfo_t status;
waitid(P_PID, cpid, &status, WEXITED);
The following error was generated:
error: ‘P_PID’ undeclared (first use in this function)
I included the following libraries:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <time.h>
Did I miss something?
Another question is that how can I use WIFSIGNALED() to retrieve information from type siginfo_t?

You need to include <sys/wait.h> and define _XOPEN_SOURCE, as documented in the manual.
The WIFSIGNALED macro must be used with the integer status obtained from wait, waitpid or waitid. In the case of waitpid, the status is available as the si_status member of the siginfo_t structure. In other words, you would use WIFSIGNALED(info.si_status), info being a structure of type siginfo_t whose address you previously passed to waitid().

Related

How to enable the usage of fork(), wait() and execv()

I have an assignment to do which requires me to use fork(), wait and execv(). However, every time I try to use them I get an error that they aren't defined. Here is my code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
fork();
printf("Hello world!\n");
return 0;
}
Here is the errors I get:
I would appreciate it if anyone could help.

F_GETPIPE_SZ undeclared

I'm trying to get size of pipe:
printf("pipe 0 size: %d bytes\npipe 1 size: %d bytes\n", fcntl(fd[0], F_GETPIPE_SZ), fcntl(fd[1], F_GETPIPE_SZ));
Used headers (half of them used by another parts of code):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
When I'm trying to compile, gcc fails with this error:
‘F_GETPIPE_SZ’ undeclared (first use in this function)
kernel version - 5.4.0-88-generic
libc6-dev version - 2.31-0ubuntu9.2
gcc version - 4:9.3.0-1ubuntu2
Since this macro is not part of POSIX, you must define the _GNU_SOURCE feature test macro before including <fcntl.h>.
This is stated in the fcntl(2) man page, in the "Conforming To" section.
See What does "#define _GNU_SOURCE" imply?

How to redirect signal to child process from parent process?

I am trying to understand processes in C. I currently want to create shell-like structure which - after pressing a shortcut like Ctrl+C or Ctrl+Z will kill all its subprocesses but will stay alive. My code looks like this:
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
pid_t pid;
void send_signal(int signum){
kill(pid, signum);
}
void init_signals(){
signal(SIGINT, send_signal);
signal(SIGTSTP, send_signal);
}
int main(){
init_signals();
pid = fork();
if(pid > 0){
//Parent Process
wait(NULL);
} else {
// Child Process
while(1){
usleep(300000);
}
}
return 0;
}
Problem here is that, when I press Ctrl+C, parent redirects it to child and kills it but when I press Ctrl+Z (even though child process is stopped) parent still hangs on wait(NULL). Any suggestions on how to fix this?
You can check here how to use wait in C . Long story short:
The wait system-call puts the process to sleep and waits for a child-process to end. It then fills in the argument with the exit code of the child-process (if the argument is not NULL).
wait doesn't get signaled until the child process ends, so just by sending the child to sleep there is no reason for the main process to continue. If you want any setup where the main process still works while the child does as well (including when it sleeps!) you can't wait on the child.
Wouldn't make sense for a shell either - it's always active in the background. Instead you need a better handler on main - like waiting on a condition. That way, when sending a child to sleep, you can signal the condition and keep going.
Apart from the solution at https://stackoverflow.com/a/49346549/5694959 I would like to suggest one more solution as to handle signals for parent process only.This way parent will execute signal handler and default action will be performed for child process. Use waitpid() to get the status of child.
waitpid(pid, NULL, WUNTRACED);
Now parent will resume its execution when child process changes its state i.e. either terminated or stopped.
Update your code as follows:
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
pid_t pid;
void send_signal(int signum){
kill(pid, signum);
}
void init_signals(){
signal(SIGINT, send_signal);
signal(SIGTSTP, send_signal);
}
int main(){
pid = fork();
if(pid > 0){
//Parent Process
init_signals();
waitpid(pid, NULL, WUNTRACED);
printf("I think this is what you are expecting...\n");
} else {
// Child Process
while(1){
usleep(300000);
}
}
return 0;
}
Just one thing to keep in mind that please make sure that parent process
has handled signal before you press ctrl + c or ctrl + z otherwise, default action of signal will be performed for parent as well.

Can't use sa_sigaction - "sigaction doens't have a field sa_sigaction"

Hey guys I am messing around with signals, and have a weird error:
I want to set a value to the member sa_sigaction but IDE and compiler seem to not find it..
#define _POSIX_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <bits/siginfo.h>
struct sigaction new_action;
void SIGUSR1_handler(int sig, siginfo_t *siginfo, void *context) {
......
}
memset(&new_action, '\0', sizeof(new_action)); //cleaning the memory
new_action.sa_sigaction = SIGUSR1_handler; //setting the handler for the signal
new_action.sa_flags = SA_SIGINFO;
I only posted the relevant part of the code.
Can anybody help me out here?
EDIT: And how can I put something in the siginfo struct or context pointer?
You don't specify your OS so I can't be sure, but I think the problem is that you're inadvertently requesting an ancient version of POSIX that lacks it via the following incorrect feature test macro usage:
#define _POSIX_SOURCE
The _POSIX_SOURCE macro itself is deprecated; you should be using _POSIX_C_SOURCE and defining it to the version of the API you want. To ensure the availability of a working sigaction, you probably want:
#define _POSIX_C_SOURCE 200809L
since it was (if I recall correctly) an XSI extension in earlier versions of the standard. Alternatively you might use:
#define _XOPEN_SOURCE 600 /* or 700 */
since the functionality you want was available as an XSI extension in Issue 6.

C error - wait()

I write a program using memory segments but the problem is my wait() is throwing me an error
error:
ks.c:24:2: error: incompatible type for argument 1 of ‘wait’
/usr/include/x86_64-linux-gnu/sys/wait.h:116:16: note: expected ‘__WAIT_STATUS’ but argument is of type ‘int’
s.c:13:6: warning: unused variable ‘w’ [-Wunused-variable]
Code line is simple wait(1); and i have includeted all neccesarry ehaders for the project why do i get that error, since it should work like this...
imports
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <errno.h>
#include "st.h"
If you check the documentation for wait, what it takes as parameter is a pointer to int where to set the status. Since this is homework, I'll let you conclude the solution yourself.
If you look at the manual page for wait it requires a pointer to an integer.
So your code should read something like
int status;
wait(&status);
The wait function actually take a pointer to an int and returns the exit status of the thread's child in that pointer.
Try something like this
int status;
wait(&status);
Read the error message thoroughly. It says incompatible type for argument 1 of ‘wait’ and then note: expected ‘__WAIT_STATUS’ but argument is of type ‘int’. You can then have a look in the manual $ man wait where everything's very shortly explained - argument and return types, typical values, etc. You might even get lucky and find an example without even searching the net.
If you were missing a .header file, you would have gotten a different error message

Resources