SIGUSR1 not received - linux

This is my first Program....ctrlcsignal.c
enter code here
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void signal_handler(int sigNo)
{
//if Ctrl+c signal
if(sigNo==SIGINT){
printf("value of SIGINT:-%d\t",SIGINT);
printf("received SIGINT\n");
}
// if some other signal , but this part wont get executed
// as the signal_handler function is registered with SIGINT only
else
{
printf("Some other signal found");
printf("value of other signal:-%d",sigNo);
}
}
int main(void)
{
//registering the signal handler function with a signal
kill(19574,SIGUSR1);
if(signal(SIGINT,signal_handler)==SIG_ERR)
{
printf("\n can't catch SIGINT\n");
}
while(1) //infinite loop
sleep(1); // 1s ,so that the CPU is not busy
return 0;
}
and this my second program....userdefinedsignals.c
enter code here
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void signal_handler(int sigNo)
{
printf("function entered...");
// check for userdefined Signal SIGUSR1
if (sigNo == SIGUSR1)
{
printf("received SIGUSR1 with value :- %d",SIGUSR1);
}
//checking for KILL Signal
else if (sigNo == SIGKILL)
{
printf("received SIGKILL with value :- %d",SIGKILL);
}
//checking for STOP Signal
else if (sigNo == SIGSTOP)
{
printf("received SIGSTOP with value :- %d",SIGSTOP);
}
// if some other signal , but this part wont get executed
// as the signal_handler function is registered with SIGINT only
else
{
printf("Some other signal found");
printf("value of other signal:-%d",sigNo);
}
}
int main(void)
{
int pid_t;
printf("process id is %d",getpid());
//registering the signal handler function with a signal
if(signal(SIGUSR1,signal_handler) == SIG_ERR)
{
printf("\n can't catch SIGSIGUSR1\n");
}
if(signal(SIGKILL,signal_handler)==SIG_ERR)
{
printf("\n can't catch SIGKILL\n");
}
if(signal(SIGSTOP,signal_handler)==SIG_ERR)
{
printf("\n can't catch SIGSTOP\n");
}
while(1) //infinite loop
sleep(1); // 1s ,so that the CPU is not busy
return 0;
}
I get the pid of the second process ... suppose xxxx
then i use the following command...
enter code here
kill -USR1 xxxx
but it shows nothing ....
also then i tried by calling the following function int the first program...but no use..
enter code herekill(xxxx,SIGUSR1);
HELP ME..!!!!

Works here.
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdarg.h> /* vsnprintf() */
#include <signal.h> /* signal */
void myprintf(FILE *fp, char *fmt, ...)
{
char buff[512];
int rc,fd;
va_list argh;
va_start (argh, fmt);
rc = vsnprintf(buff, sizeof buff, fmt, argh);
if (rc < 0 || rc >= sizeof buff) {
rc = sprintf(buff, "Argh!: %d:\n", rc);
}
if (!fp) fp = stderr;
fd = fileno(fp);
if (fd < 0) return;
if (rc > 0) write(fd, buff, rc);
return;
}
void signal_handler(int sigNo)
{
switch (sigNo ) {
case SIGUSR1:
myprintf(NULL, "received SIGUSR1 with value :- %d\n", SIGUSR1);
break;
case SIGKILL:
myprintf(NULL, "received SIGKILL with value :- %d\n", SIGKILL);
break;
case SIGSTOP:
myprintf(NULL, "received SIGSTOP with value :- %d\n", SIGSTOP);
break;
default:
myprintf(NULL, "Some other signal occured: %d\n", sigNo);
break;
}
return;
}
int main(void)
{
pid_t mypid;
mypid = getpid();
printf("process id is %d\n", (int) mypid);
if(signal(SIGUSR1,signal_handler) == SIG_ERR)
{ printf("\n can't catch SIGSIGUSR1\n"); }
if(signal(SIGKILL,signal_handler)==SIG_ERR)
{ printf("\n can't catch SIGKILL\n"); }
if(signal(SIGSTOP,signal_handler)==SIG_ERR)
{ printf("\n can't catch SIGSTOP\n"); }
if(signal(SIGCONT,signal_handler)==SIG_ERR)
{ printf("\n can't catch SIGCONT\n"); }
while(1) {
sleep(1);
}
return 0;
}

You're catching the signal all right, but not seeing the message because you don't terminate lines properly, and the standard output stream on your system is line buffered (assuming your program runs in a terminal).
Standard C defines three levels of buffering for output streams:
unbuffered, where output is transmitted immediately
line buffered, where output is transmitted when a newline character is encountered
fully buffered, where output is transmitted when an internal buffer fills
(This is a simplification - see a C reference or the Standard for details).
Consider:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("Hello");
pause();
}
This produces no output in a terminal. Fix it by terminating the line:
printf("Hello\n");
This will produce the expected output in a terminal.
If stdout is not connected to a terminal - for example, you redirect to a file - then the stream becomes fully buffered. This:
./a.out > foo
Ctrl-C
cat foo
produces no output, even with the newline character added. Here you need an explicit flush to transmit the output before the buffer is full.
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("Hello\n");
fflush(stdout);
pause();
}
This produces output even when redirected to a file.

Related

Error in reading from the pipe

I am getting unusual results while writing and reading from a pipe. The runtime error is Program terminated by signal: 13. I searched about this error and found that this error is due to there are no readers to read from pipe while i am reading from the pipe in the child process. Here is my code:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define BUFFER_SIZE 50
#define READ_END 0
#define WRITE_END 1
int main()
{
int pipe_fd[2];
pid_t pid;
pid = fork();
char message[BUFFER_SIZE] = "Greetings";
char read_message[BUFFER_SIZE];
if( pipe(pipe_fd) == -1)
{
perror("Error in creating the pipe \n");
exit(-1);
}
if(pid==-1)
{
perror("Error in creating the child! \n");
exit(-1);
}
if(pid==0) // Child process
{
close(pipe_fd[WRITE_END]);
read(pipe_fd[READ_END], read_message , BUFFER_SIZE);
printf("The message read by the child is: %s", read_message);
close(pipe_fd[READ_END]);
}
if(pid>0) // Parent process
{
close(pipe_fd[READ_END]); //Closing the read end of the pipe
write(pipe_fd[WRITE_END], message, BUFFER_SIZE); // Writing to pipe on write_end
close(pipe_fd[WRITE_END]);
}
return 0;
}
Any suggestions how to solve this runtime error?
You need to open your pipe before you fork a child process. Otherwise your processes aren't talking to the same pipe.
Thus move your pipe creation code above the fork() call as follows:
if( pipe(pipe_fd) == -1)
{
perror("Error in creating the pipe \n");
exit(-1);
}
pid_t pid;
pid = fork();
char message[BUFFER_SIZE] = "Greetings";
char read_message[BUFFER_SIZE];
if(pid==-1)
{
perror("Error in creating the child! \n");
exit(-1);
}

Cygwin: interrupting blocking read

I've written the program which spawns a thread that reads in a loop from stdin in a blocking fashion. I want to make the thread return from blocked read immediately. I've registered my signal handler (with sigaction and without SA_RESTART flag) in the reading thread, send it a signal and expect read to exit with EINTR error. But it doesn't happen. Is it issue or limitation of Cygwin or am I doing something wrong?
Here is the code:
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
pthread_t thread;
volatile int run = 0;
void root_handler(int signum)
{
printf("%s ENTER (thread is %x)\n", __func__, pthread_self());
run = 0;
}
void* thr_func(void*arg)
{ int res;
char buffer[256];
printf("%s ENTER (thread is %x)\n", __func__, pthread_self());
struct sigaction act;
memset (&act, 0, sizeof(act));
act.sa_sigaction = &root_handler;
//act.sa_flags = SA_RESTART;
if (sigaction(SIGUSR1, &act, NULL) < 0) {
perror ("sigaction error");
return 1;
}
while(run)
{
res = read(0,buffer, sizeof(buffer));
if(res == -1)
{
if(errno == EINTR)
{
puts("read was interrupted by signal");
}
}
else
{
printf("got: %s", buffer);
}
}
printf("%s LEAVE (thread is %x)\n", __func__, pthread_self());
}
int main() {
run = 1;
printf("root thread: %x\n", pthread_self());
pthread_create(&thread, NULL, &thr_func, NULL);
printf("thread %x started\n", thread);
sleep(4);
pthread_kill(thread, SIGUSR1 );
//raise(SIGUSR1);
pthread_join(thread, NULL);
return 0;
}
I'm using Cygwin (1.7.32(0.274/5/3)).
I've just tried to do the same on Ubuntu and it works (I needed to include signal.h, though, even though in Cygwin it compiled as it is). It seems to be peculiarity of Cygwin's implementation.

pclose() returns SIGPIPE intermittently

When the following C program is executed, and SIGUSR1 is sent to the running process repeatedly, the pclose() call will sometimes return 13. 13 corresponds to SIGPIPE on my system.
Why does this happen?
I am using while true; do kill -SIGUSR1 <process-id>; done to send SIGUSR1 to the program. The program is executed on Ubuntu 14.04.
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
void handler(int i) {}
void* task(void*)
{
FILE *s;
char b [BUFSIZ];
while (1) {
if ((s = popen("echo hello", "r")) == NULL) {
printf("popen() failed\n");
}
while (fgets(b, BUFSIZ, s) != NULL) ;
if (int r = pclose(s)) {
printf("pclose() failed (%d)\n", r);
}
}
return 0;
}
int main(int argc, char **argv)
{
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGUSR1, &action, NULL);
pthread_t tid;
pthread_create(&tid, 0, task, NULL);
pthread_join(tid, NULL);
}
This happens when fgets gets interrupted by the signal. The program doesn't read the pipe to the end and closes it. The other program then SIGPIPEs.
The correct pipe reading operation is:
do {
while (fgets(b, BUFSIZ, s) != NULL) ;
} while (errno == EINTR);

Can not get proper response from select() using writefds

Parent receives SIGPIPE sending chars to aborted child process through FIFO pipe.
I am trying to avoid this, using select() function. In the attached sample code,
select() retruns OK even after the child at the other end of pipe having been terminated.
Tested in
RedHat EL5 (Linux 2.6.18-194.32.1.el5)
GNU C Library stable release version 2.5
Any help appreciated. Thnak you.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
#include <unistd.h>
static void sigpipe_fct();
main()
{
struct stat st;
int i, fd_out, fd_in, child;
char buf[1024];
#define p_out "/tmp/pout"
signal(SIGPIPE, sigpipe_fct);
if (stat(p_out, &st) != 0) {
mknod(p_out, S_IFIFO, 0);
chmod(p_out, 0666);
}
/* start receiving process */
if ((child = fork()) == 0) {
if ((fd_in = open(p_out, O_RDONLY)) < 0) {
perror(p_out);
exit(1);
}
while(1) {
i = read(fd_in, buf, sizeof(buf));
fprintf(stderr, "child %d read %.*s\n", getpid(), i, buf);
lseek(fd_in, 0, 0);
}
}
else {
fprintf(stderr,
"reading from %s - exec \"kill -9 %d\" to test\n", p_out, child);
if ((fd_out = open(p_out, O_WRONLY + O_NDELAY)) < 0) { /* output */
perror(p_out);
exit(1);
}
while(1) {
if (SelectChkWrite(fd_out) == fd_out) {
fprintf(stderr, "SelectChkWrite() success write abc\n");
write(fd_out, "abc", 3);
}
else
fprintf(stderr, "SelectChkWrite() failed\n");
sleep(3);
}
}
}
static void sigpipe_fct()
{
fprintf(stderr, "SIGPIPE received\n");
exit(-1);
}
SelectChkWrite(ch)
int ch;
{
#include <sys/select.h>
fd_set writefds;
int i;
FD_ZERO(&writefds);
FD_SET (ch, &writefds);
i = select(ch + 1, NULL, &writefds, NULL, NULL);
if (i == -1)
return(-1);
else if (FD_ISSET(ch, &writefds))
return(ch);
else
return(-1);
}
From the Linux select(3) man page:
A descriptor shall be considered ready for writing when a call to an
output function with O_NONBLOCK clear would not block, whether or not
the function would transfer data successfully.
When the pipe is closed, it won't block, so it is considered "ready" by select.
BTW, having #include <sys/select.h> inside your SelectChkWrite() function is extremely bad form.
Although select() and poll() are both in the POSIX standard, select() is much older and more limited than poll(). In general, I recommend people use poll() by default and only use select() if they have a good reason. (See here for one example.)

Logging a message from SIGTERM

What's the proper way to log a shutdown message when an application (a C++ daemon, in my case) receives a SIGTERM or SIGINT?
According to CERT and the signal(7) manpage, many functions (including, presumably, those used by most logging libraries) aren't safe to call from signal handlers.
Vlad Lazarenko wrote a great blog post earlier this year on this very topic. On Linux it boils down to creating a signal descriptor with signalfd(2) and use an event loop such as poll(2) or epoll_wait(2). Here is Vlad's example reading from the descriptor
#include <sys/signalfd.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
sigset_t mask;
int sfd;
struct signalfd_siginfo fdsi;
ssize_t s;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
/* Block signals so that they aren't handled
according to their default dispositions */
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
handle_error("sigprocmask");
sfd = signalfd(-1, &mask, 0);
if (sfd == -1)
handle_error("signalfd");
for (;;) {
s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
if (s != sizeof(struct signalfd_siginfo))
handle_error("read");
if (fdsi.ssi_signo == SIGINT) {
printf("Got SIGINT\n");
} else if (fdsi.ssi_signo == SIGQUIT) {
printf("Got SIGQUIT\n");
exit(EXIT_SUCCESS);
} else {
printf("Read unexpected signal\n");
}
}
}
This example can easily be extended to integrate into an event loop.
Logging could be done not from handler, but after it:
int received_sigterm = 0;
void
sigterm_handler(int sig)
{
received_sigterm = 1;
}
void
loop(void)
{
for(;;) {
sleep(1);
if (received_sigterm)
log("finish\n");
}
}
int
main()
{
log("start\n");
signal(SIGTERM, sigterm_handler);
loop();
}
The concept is borrowed from openssh-6.1 sources.

Resources