I have this solution for an exercise I was doing but when I try to run it
and send SIGUSR1 the terminal shows "Stack fault", and I don't know why.
It shows nothing when I send SIGUSR2, but the thing is that with SIGTERM and SIGINT the program works.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
void manejador(int signum){
switch (signum){
case SIGUSR1:
printf("He recibido la señal SIGUSR1\n");
break;
case SIGUSR2:
printf("He recibido la señal SIGUSR2\n");
break;
case SIGTERM:
printf("Fin de ejecucion\n");
exit(EXIT_SUCCESS);
}
}
int main(int argc, char *argv[])
{
if (signal(SIGUSR1, manejador) == SIG_ERR) {
perror("error en la señal SIGUSR1");
exit(EXIT_FAILURE);
}
if (signal(SIGUSR2, manejador) == SIG_ERR) {
perror("error en la señal SIGUSR2");
exit(EXIT_FAILURE);
}
if (signal(SIGTERM, manejador) == SIG_ERR) {
perror("error en SIGTERM");
exit(EXIT_FAILURE);
}
if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
perror("error en SIGINT");
exit(EXIT_FAILURE);
}
while (1)
pause();
}
Related
i'm trying to start a IPC's related project and under my point of view I have to start handling signals. When it's time to press Ctrl+C the handler function starts correctly but in console it appears printed twice.
Another curious situation is that if I change the character to an empty string, the parent process sleeps 10 secs properly and then receives the SIGINT.
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>
void handler(int);
/*typedef struct {
int semaforo;
//iremos añadiendo mas a medida que necesitemos, pero para pasar todos como un
solo argumento a la función manejadora es más comodo. }ipces;*/
int semaforo;
int main() {
// ipces ipces;
semaforo = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600);
semctl(semaforo, 0, SETVAL, 1);
struct sigaction newact, oldact;
struct sembuf semoper, semoper1;
sigset_t mask;
newact.sa_handler = handler;
sigemptyset(&mask);
// nueva.sa_mask=mask;
// newact.sa_flags=SA_RESTART;
sigaction(SIGINT, &newact, &oldact);
int pid = fork();
switch (pid) {
case -1:
perror("Error en el forking");
kill(getpid(), SIGINT); // envía sigint a el mismo proceso que lo
// invoca, e inicia la manejadora
break;
case 0: // hijo
while (1) {
printf("*");
}
break;
default:
semoper.sem_op = -1;
semoper.sem_num = 0;
semop(semaforo, &semoper, 0);
sleep(10);
// hacemos que haga cosas y si todo ha ido bien lanzamos SIGINT ->
// LANZARÁ LA MANEJADORA
kill(getpid(), SIGINT);
break;
}
}
void handler(int sig) {
printf("SIGINT");
if (semctl(semaforo, 0, IPC_RMID) == 1) {
printf("Error borrando semaforo;");
}
// system("clear");
exit(3);
}
So, I've made a function in C that "daemonizes" a program, but when I do so, any code I want the daemon to execute, is not executed... even though the daemon is up and running in the background.
void makeDaemon(){
int i,fd0,fd1,fd2;
pid_t pid;
struct sigaction sa;
struct rlimit rl;
umask(0);
if(getrlimit(RLIMIT_NOFILE, &rl)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
setsid();
sa.sa_handler=SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
if(sigaction(SIGHUP, &sa, NULL)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
if(chdir("/")<0) exit(EXIT_FAILURE);
if(rl.rlim_max=RLIM_INFINITY) rl.rlim_max=1024;
for(i=0;i< rl.rlim_max; i++) close(i);
fd0=open("/dev/null",O_RDWR);
fd1=dup(0);
fd2=dup(0);
if(fd0!=0 || fd1!=1 || fd2!=2) exit(EXIT_FAILURE);
}
This is the "daemonizing" function, and this is an other program that I want to daemonize but it just doesnt do what it should...
int main(int argc, char ** argv){
makeDaemon();
char* path="./run/pipes/saturnd-request-pipe";
char* path2="./run/pipes/saturnd-reply-pipe";
//Creation d'un pipe au cas où il n'existe pas
//mkfireply_pipe(path,0666);
//Ouverture du pipe
int request_pipe;
request_pipe=open(path,O_RDONLY);
if(request_pipe==-1){
perror("Erreur d'ouverture du pipe");
return -1;
}
int reply_pipe;
reply_pipe=open(path2,O_WRONLY);
if(reply_pipe==-1){
perror("Erreur d'ouverture du pipe");
return -1;
}
char tmp1[2];
read(request_pipe,tmp1,2);
printf("%s",tmp1);
}
If someone has any advice on how to connect the two, I'd greatly appreciate it.
I want to write a code using pipes. This code is about the rock, scissor, paper game, so I need to ask and receive messages all the time until one of two players score 3. So far, now I have the following code, but I don´t know how to iterate this code, could be with a while iteration?
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define READ_END 0 /* index pipe extremo escritura */
#define WRITE_END 1 /* index pipe extremo lectura */
int main(int argc, char* argv[])
{
int fd1[2],fd2[2];
int status, pid;
pipe(fd1); /* comunica ls y grep */
pid = fork();
if(pid == 0) /* hijo 1*/
{
close(fd1[READ_END]); /* cerrar extremo no necesario */
dup2(fd1[WRITE_END], STDOUT_FILENO);
close(fd1[WRITE_END]);
}
else /* padre */
{
close(fd1[WRITE_END]); /* extremo no necesario ya */
pipe(fd2); /* comunica grep y wc */
pid = fork();
if(pid == 0) /* hijo 2 */
{
close(fd2[READ_END]); /* cerrar extremo no necesario */
dup2(fd1[READ_END], STDIN_FILENO);
close(fd1[READ_END]);
dup2(fd2[WRITE_END], STDOUT_FILENO);
close(fd2[WRITE_END]);
}
else /* padre */
{
close(fd1[READ_END]); /* cerrar extremo no necesario */
close(fd2[WRITE_END]); /* cerrar extremo no necesario */
}
}
close(fd2[READ_END]); /* cerrar extremo que queda abierto en el padre */
/* wait para cada hijo */
wait(&status);
wait(&status);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void) {
int pfd1[2];
int pfd2[2];
pid_t pid1, pid2, pid3;
if(pipe(pfd1)==-1) {
perror("Creazione pipe");
exit(EXIT_FAILURE);
}
if(pipe(pfd2)==-1) {
perror("Creazione pipe");
exit(EXIT_FAILURE);
}
printf("Sono il padre\n");
switch(pid1=fork()) {
printf("%d\n", pid1);
case -1: {
perror("Creazione figlio 1");
exit(EXIT_FAILURE);
}
case 0: { //figlio 1
printf("Sono il figlio 1\n");
if(dup2(pfd1[1],1)==-1) { //redirige lo stdout sul descrittore scrittura
perror("Prima redirezione");
exit(EXIT_FAILURE);
}
close(pfd1[0]);
close(pfd1[1]); //lo chiudo perchè sto redirigendo lo stdout
close(pfd2[0]);
close(pfd2[1]);
execlp("ps", "ps", "-A", "-ostat,pid", (char*) NULL);
}
}
waitpid(pid1,NULL,0);
switch(pid2=fork()) {
case -1: {
perror("Creazione figlio 2");
exit(EXIT_FAILURE);
}
case 0: { //figlio 2
printf("Sono il figlio 2\n");
if(dup2(pfd1[0],0)==-1) { //redirige lo stdin sul descrittore lettura
perror("Seconda redirezione");
exit(EXIT_FAILURE);
}
printf("Prima redirezione figlio 2\n");
if(dup2(pfd2[1],1)==-1) {
perror("Terza redirezione");
exit(EXIT_FAILURE);
}
close(pfd1[1]);
close(pfd1[0]);
close(pfd2[0]);
close(pfd2[1]);
execlp("grep", "grep", "-e", "[zZ]", (char*) NULL);
}
waitpid(pid2, NULL,0);
switch(pid3=fork()) {
case -1: {
perror("Creazione terzo figlio");
exit(EXIT_FAILURE);
}
case 0: { //figlio 3
printf("Sono il figlio 3\n");
if(dup2(pfd2[0],0)==-1) {
perror("Quarta redirezione");
exit(EXIT_FAILURE);
}
close(pfd1[0]);
close(pfd1[1]);
close(pfd2[0]);
close(pfd2[1]);
execlp("awk", "awk", "'{print $2}'", (char*) NULL);
}
}
/*padre*/
//waitpid(pid1, NULL, 0);
//waitpid(pid2, NULL, 0);
waitpid(pid3, NULL, 0);
close(pfd2[0]);
close(pfd2[1]);
close(pfd1[0]);
close(pfd1[1]);
return 0;
}
}
Hello,
I'm trying to create a pipe of shell bash commands using the system call dup2.
The output I expect should be the same as
bash $> ps -A -ostat,pid | grep -e [zZ] | awk '{print $2}'
what I do is forking 3 children and make them communicate through two pipes. Each one of the children executes one part of the command.
The problem is my program gets stuck on the second child which apparently doesn't even get to do the exec.
I'm sure there are some problems with my code, but since it's the first time for me trying to use dup2 I'm a bit confused.
Also, don't mind the printfs, they're just for debugging.
Thanks a lot!
Basically you have to close pipes in the right positions and you failed to close a bracket in the switch statement. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h> /*lib for waitpid()*/
int main(void) {
int pfd1[2];
int pfd2[2];
pid_t pid1, pid2, pid3;
if(pipe(pfd1)==-1) {
perror("Creazione pipe");
exit(EXIT_FAILURE);
}
if(pipe(pfd2)==-1) {
perror("Creazione pipe");
exit(EXIT_FAILURE);
}
printf("Sono il padre\n");
switch(pid1=fork()) {
printf("%d\n", pid1);
case -1: {
perror("Creazione figlio 1");
exit(EXIT_FAILURE);
}
case 0: { //figlio 1
printf("Sono il figlio 1\n");
if(dup2(pfd1[1],1)==-1) { //redirige lo stdout sul descrittore scrittura
perror("Prima redirezione");
exit(EXIT_FAILURE);
}
close(pfd1[0]);
close(pfd1[1]); //lo chiudo perchè sto redirigendo lo stdout
close(pfd2[0]);
close(pfd2[1]);
execlp("ps", "ps", "-A", "-ostat,pid", (char*) NULL);
}
}
waitpid(pid1,NULL,0);
switch(pid2=fork()) {
case -1: {
perror("Creazione figlio 2");
exit(EXIT_FAILURE);
}
case 0: { //figlio 2
printf("Sono il figlio 2\n");
if(dup2(pfd1[0],0)==-1) { //redirige lo stdin sul descrittore lettura
perror("Seconda redirezione");
exit(EXIT_FAILURE);
}
printf("Prima redirezione figlio 2\n");
if(dup2(pfd2[1],1)==-1) {
perror("Terza redirezione");
exit(EXIT_FAILURE);
}
close(pfd1[0]);
close(pfd1[1]);
close(pfd2[0]);
close(pfd2[1]);
execlp("grep", "grep", "-e", "[Ss]", (char*) NULL);
}
} /*You forgot that bracket*/
/*
* Close the pipe before waitpid because 2rd child
* will wait until you close it. Check pipe theory
*/
close(pfd1[1]);
close(pfd1[0]);
waitpid(pid2, NULL,0);
switch(pid3=fork()) {
case -1: {
perror("Creazione terzo figlio");
exit(EXIT_FAILURE);
}
case 0: { //figlio 3
printf("Sono il figlio 3\n");
if(dup2(pfd2[0],0)==-1) {
perror("Quarta redirezione");
exit(EXIT_FAILURE);
}
close(pfd2[0]);
close(pfd2[1]);
/*' ' removed from the "{print $2}"*/
execlp("awk", "awk", "{print $2}", (char*) NULL);
}
}
/*
* Close the pipe before waitpid because 3rd child
* will wait until you close it. Check pipe theory
*/
close(pfd2[0]);
close(pfd2[1]);
waitpid(pid3, NULL, 0);
return 0;
}
Hi I've this problem to solve with a functional program in C.
"Write a C program where a process F create a childprocess C.
The childprocess C waits the user to type the password, if is correct sends a signal SIGUSR1 to the father, if after 3 attempts the password is still incorrect it will send a SIGUSR2 signal to the father and terminate; if it receives from the father SIGUSR1 signal must stop viewing the "timeout" message.
His father after 30 seconds (if it has not received any signal from the child) must send the signal SIGUSR1 to the child and end with exit(1); if it receives the SIGUSR1 signal must end with exit(0); if it receives the signal SIGUSR2 must end with exit (2)."
I'm trying to solve it but I'm stuck. This is what I've done:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
exit(2);
}
}
void childprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[], password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (enteredpassword == password)
signal(SIGUSR1, fatherprocess);
} else {
signal(SIGUSR2, fatherprocess);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
signal(SIGUSR1, childprocess);
}
}
return 0;
}
I've edited my program in this way:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal, int fatherpid){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
kill(fatherpid, SIGUSR1);
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
kill(fatherpid, SIGUSR2);
exit(2);
}
}
void childprocess(int mysignal, int childpid){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
kill(childpid, SIGUSR1);
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[] = "test", password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (strcmp(enteredpassword, password) == 0)
fatherprocess(SIGUSR1, fatherpid);
} else {
fatherprocess(SIGUSR2, fatherpid);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
childprocess(SIGUSR1, childpid);
}
}
return 0;
}
Now it works perfectly but I don't know if I've respected the exercise text.
As was mentioned in the comments (by Jonathan Leffler), you need to use the kill() system call (to send the signals) and register a signal handler using a call like sigaction(). I have linked these two calls to online manual pages that provide additional information about them.
Here's some code that demonstrates how these can be used towards achieving your stated goal. You will still need to add/modify the code for things like the prompts you want and the acceptable input string. Please note that I'm not claiming this to be the best way to do it, only that it's an example of how it could be done (it compiled and worked for me):
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
static void get_password(char* buf, int maxbuf)
{
fgets(buf, maxbuf, stdin);
}
static int is_password_correct(char* buf)
{
return buf[0] == 'a';
}
volatile int got_signal = 0;
volatile int child_signal = 0;
static void parent_sig_handler(int signum)
{
if (!got_signal)
{
got_signal = signum;
printf("parent_sig_handler: got sig %d\n", signum);
}
}
static void child_sig_handler(int signum)
{
if (!child_signal)
{
child_signal = signum;
printf("child_sig_handler: got sig %d\n", signum);
}
}
int main()
{
struct sigaction act;
sigfillset(&act.sa_mask);
act.sa_handler = parent_sig_handler;
sigaction(SIGALRM, &act, NULL);
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGUSR2, &act, NULL);
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("error forking");
exit(3);
}
if (child_pid == 0)
{
printf("child running\n");
act.sa_handler = child_sig_handler;
sigaction(SIGUSR1, &act, NULL);
pid_t parent_pid = getppid();
for (int i = 0; i < 3; ++i)
{
char passwd[64];
passwd[0] = '\0';
get_password(passwd, sizeof(passwd));
if (is_password_correct(passwd))
{
kill(parent_pid, SIGUSR1);
exit(0);
}
}
kill(parent_pid, SIGUSR2);
exit(2);
}
printf("parent running\n");
alarm(30); /* sets parent up to receive a SIGALRM signal in 30 seconds */
sigset_t sigmask;
sigemptyset(&sigmask);
while (!got_signal)
{
sigsuspend(&sigmask);
}
switch (got_signal)
{
case SIGALRM:
kill(child_pid, SIGUSR1);
exit(1);
case SIGUSR1:
exit(0);
case SIGUSR2:
exit(2);
default:
exit(3);
}
exit(3);
}