I wrote a program that uses the sigpending ()
function. The program returns blocked or pending signals.
My question is, what else could I improve or what problems does implementation have? Possible bugs?
code:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void catcher(int signum) {
puts("inside catcher!");
if (signum != 0)
perror("signum error");
}
void check_pending(int signum, char * signame) {
sigset_t sigset;
if (sigpending( & sigset) != 0)
perror("sigpending() error");
else if (sigismember( & sigset, signum))
printf("a %s signal is pending\n", signame);
else
printf("no %s signals are pending\n", signame);
}
int main() {
struct sigaction sigact;
sigset_t sigset;
sigemptyset( & sigact.sa_mask);
sigact.sa_flags = 0;
sigact.sa_handler = catcher;
if (sigaction(SIGUSR1, & sigact, NULL) != 0)
perror("sigaction() error");
else {
sigemptyset( & sigset);
sigaddset( & sigset, SIGUSR1);
if (sigprocmask(SIG_SETMASK, & sigset, NULL) != 0)
perror("sigprocmask() error");
else {
puts("SIGUSR1 signals are now blocked");
kill(getpid(), SIGUSR1);
printf("after kill: ");
check_pending(SIGUSR1, "SIGUSR1");
sigemptyset( & sigset);
sigprocmask(SIG_SETMASK, & sigset, NULL);
puts("SIGUSR1 signals are no longer blocked");
check_pending(SIGUSR1, "SIGUSR1");
}
}
}
1 Answer 1
what else could I improve or what problems does implementation have?
Just some little ideas. Sorry, not much sig...()
feedback.
Lack of documentation
At least some comments in the .c file to indicate overall functionality.
Use const
Use const
to allow call with a const char *
and to better convey function's use of signame
.
// void check_pending(int signum, char * signame)
void check_pending(int signum, const char * signame)
Clearer message
Consider a sentence and not lower case.
Example below, but applies to other output as well.
// printf("a %s signal is pending\n", signame);
printf("A %s signal is pending.\n", signame);
From time-to-time and especially in error messages, it is really nice to see a string printed with sentinels (like quote-marks). It is useful in seeing what part of output is format and what is data.
printf("A \"%s\" signal is pending.\n", signame);
In error message this in even more important as something went wrong. Maybe the string has unexpected leading/trailing white-space that is messing up the operation?
Fully initialize
Consider these 2 code snippets. The 2nd one fully initializes sigact
- even members that are not obviously important.
// OP
struct sigaction sigact;
sigemptyset( & sigact.sa_mask);
sigact.sa_flags = 0;
sigact.sa_handler = catcher;
// Suggested
// This initializes all members, not just .sa_flags, .sa_handler.
struct sigaction sigact = { .sa_flags = 0, .sa_handler = catcher };
sigemptyset( & sigact.sa_mask);
Define in needed block, not above
// sigset_t sigset;
...
else {
sigset_t sigset;
sigemptyset( & sigset);
Error check
kill()
, sigprocmask()
, and other process functions deserve a check of their return values.
Error return
After perror("sigprocmask() error");
, I'd expect a different return value like return EXIT_FAILURE;
so calling scripts can differentiate.
Style
There are various style issues that I do not prefer like: missing {}
on one-liners, void
-less main()
, spaced use of unary &
, pointer *
, 4-space indent. Yet it is more important to employ a constant style than to promote my preference. OP's code is consistent and that is good.
I do like subtle good style bits like alphabetized include
.