Reputation: 795
I have a problem running the below code , which invokes getutent() to count the total number of users currently logged in to the system. The timer will be invoked every 1sec and will set the boolean named "isSigAlrmOccured" to true and exit.The main function checks whether the timer signal is delivered by checking this boolen and monitor the number of loggedin users. Unfortunately, the timer signal is delivered to the main program only two times correctly and I don't get any further signals after that. The pause function call doesn't get interrupted after the first two signals.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <utmp.h>
#include <errno.h>
static int isSigAlrmOccured;
void alarm_handler (int signo)
{
static int i=1;
printf("\n Signal Occurred %d times\n",i++);
isSigAlrmOccured = 1;
}
int main (int argc, char *argv[]) {
struct itimerval delay;
struct utmp *utmpstruct;
int numuser;
int ret;
signal (SIGALRM, alarm_handler);
delay.it_value.tv_sec = 1;
delay.it_value.tv_usec = 0;
delay.it_interval.tv_sec = 1;
delay.it_interval.tv_usec = 0;
ret = setitimer (ITIMER_REAL, &delay, NULL);
if (ret) {
perror ("setitimer");
return 0;
}
for (;;) {
pause ( );
/* count the number of users */
if ( (errno == EINTR) && (isSigAlrmOccured) ) {
isSigAlrmOccured = 0;
setutent();
while ((utmpstruct = getutent())) {
if ((utmpstruct->ut_type == USER_PROCESS) &&
(utmpstruct->ut_name[0] != '\0'))
numuser++;
}
endutent();
}
}
return 0;
}
Output:
Signal Occurred 1 times
Signal Occurred 2 times
Upvotes: 2
Views: 1223
Reputation: 1684
The implementation of *utent() is using alarm() and is reseting your alarm.
You'll have to do something else.
strace ttest ( some lines removed for brevity )
[...]
pause()
--- SIGALRM (Alarm clock) @ 0 (0) ---
write(1, " Signal Occurred 1 times\n", 25 Signal Occurred 1 times) = 25
open("/var/run/utmp", O_RDONLY|O_CLOEXEC) = 3
alarm(0) = 5
rt_sigaction(SIGALRM, {0x7f52580a91c0, [], SA_RESTORER, 0x7f5257fd46e0}, {0x40075c, [ALRM], SA_RESTORER|SA_RESTART, 0x7f5257fd46e0}, 8) = 0
alarm(1) = 0
Example code which only sets the alarm during the sleep period.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <utmp.h>
#include <errno.h>
static int isSigAlrmOccured;
void alarm_handler (int signo)
{
static int i=1;
printf("\n Signal Occurred %d times\n",i++);
isSigAlrmOccured = 1;
}
int main (int argc, char *argv[]) {
struct itimerval delay;
struct utmp *utmpstruct;
int numuser;
int ret;
for (;;) {
signal (SIGALRM, alarm_handler);
alarm(1); /* wake me later */
pause ( );
/* count the number of users */
if ( (errno == EINTR) && (isSigAlrmOccured) ) {
signal (SIGALRM, SIG_DFL);
isSigAlrmOccured = 0;
numuser = 0;
setutent();
while ((utmpstruct = getutent())) {
if ((utmpstruct->ut_type == USER_PROCESS) &&
(utmpstruct->ut_name[0] != '\0'))
numuser++;
}
endutent();
printf("found %d users\n", numuser);
}
}
return 0;
}
Upvotes: 7