Thread: Advice needed on correct usage of the pause() and alarm() functions...

  1. #1
    Registered User JM1082's Avatar
    Join Date
    Mar 2011
    Posts
    51

    Advice needed on correct usage of the pause() and alarm() functions...

    Hi all,

    I'm trying to write a program which will give two processes 5 seconds each to write their message to the screen.

    The problem is that the pause function isn't unpausing when the second process emits it's SIGALRM...

    Would somebody please be able to advise me on where I'm going wrong?

    Please see my code below:

    Code:
    /*  */
    
    
    
    // Pre-processor Directives /////////////////////////////////////
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <wait.h>
    #include <signal.h>
    
    /////////////////////////////////////////////////////////////////
    
    
    
    // Function Prototypes //////////////////////////////////////////
    
    void handler( int );
    
    /////////////////////////////////////////////////////////////////
    
    
    
    // Main Function Implementation /////////////////////////////////
    
    int i = 1, j = 1;
    
    int main( void )
    {
    	if( fork() != 0 )
    	{
    		while( 1 )
    		{
    			signal( SIGALRM, handler );
    			if( i == 1 )
    			{
    				alarm( 5 );
    				i--;
    			}
    			printf( "[PARENT] Serving HTTP Session 2\n" );fflush( stdout );
    		}
    	}
    	else
    	{
    		sleep( 5 ); /* Allow the parent to get ready. */
    		while( 1 )
    		{
    			signal( SIGALRM, handler );
    			if( j == 1 )
    			{
    				alarm( 5 );
    				j--;
    			}
    			printf( "[CHILD] Serving HTTP Session 1\n" );fflush( stdout );
    		}
    	}
    	exit( EXIT_SUCCESS );
    }
    
    /////////////////////////////////////////////////////////////////
    
    
    
    // Sub-function Implementation //////////////////////////////////
    
    void handler( int SIG )
    {
    	printf( "[HANDLER] Signal recieved!\n" );fflush( stdout );
    	signal( SIG, handler );
    	pause(); /* Pause the process until the other process sends it's alarm signal. */
    	if( i == 0 )
    		i++;
    	if( j == 0 )
    		j++;
    }
    
    /////////////////////////////////////////////////////////////////

  2. #2
    Registered User
    Join Date
    Nov 2011
    Location
    Buea, Cameroon
    Posts
    197
    first of all i think the logic of the first and second while loops is not the best the while(1) thing would not stop since its always true. don't you have a better way to check the fork() function without including an infinite loop inside???

  3. #3
    Registered User JM1082's Avatar
    Join Date
    Mar 2011
    Posts
    51
    Quote Originally Posted by Nyah Check View Post
    first of all i think the logic of the first and second while loops is not the best the while(1) thing would not stop since its always true. don't you have a better way to check the fork() function without including an infinite loop inside???
    The program is never meant to stop, just continually print whichever process isn't paused! Hence infinite loops!

  4. #4
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Why are you calling pause from inside your signal handler? I'm pretty sure that won't do anything useful unless you explicitly make signals reentrant (but you might end up with a stack overflow if you do that in your current code).

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Is this what you want?
    Code:
    /*  */
    
    
    
    // Pre-processor Directives /////////////////////////////////////
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <wait.h>
    #include <signal.h>
    
    /////////////////////////////////////////////////////////////////
    
    
    
    // Function Prototypes //////////////////////////////////////////
    
    void handler( int );
    
    /////////////////////////////////////////////////////////////////
    
    
    
    // Main Function Implementation /////////////////////////////////
    
    int i = 1, j = 1;
    
    int main( void )
    {
        if( fork() != 0 )
        {
            while( 1 )
            {
                signal( SIGALRM, handler );
                if( i == 1 )
                {
                    alarm( 5 );
                    i--;
                }
                printf( "[PARENT] Serving HTTP Session 2\n" );fflush( stdout );
                pause();
            }
        }
        else
        {
    //        sleep( 5 ); /* Allow the parent to get ready. */
            while( 1 )
            {
                signal( SIGALRM, handler );
                if( j == 1 )
                {
                    alarm( 5 );
                    j--;
                }
                printf( "[CHILD] Serving HTTP Session 1\n" );fflush( stdout );
                pause();
            }
        }
        exit( EXIT_SUCCESS );
    }
    
    /////////////////////////////////////////////////////////////////
    
    
    
    // Sub-function Implementation //////////////////////////////////
    
    void handler( int SIG )
    {
        printf( "[HANDLER] Signal recieved!\n" );fflush( stdout );
        if( i == 0 )
            i++;
        if( j == 0 )
            j++;
    }
    In the manual page for alarm, note this:
    NOTES
    alarm() and setitimer(2) share the same timer; calls to one will interfere with use of the other.

    sleep(3) may be implemented using SIGALRM; mixing calls to alarm() and sleep(3) is a bad idea.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User JM1082's Avatar
    Join Date
    Mar 2011
    Posts
    51
    Quote Originally Posted by christop View Post
    Why are you calling pause from inside your signal handler? I'm pretty sure that won't do anything useful unless you explicitly make signals reentrant (but you might end up with a stack overflow if you do that in your current code).
    So would you recommend I send the SIGALRM from the handler?

  7. #7
    Registered User JM1082's Avatar
    Join Date
    Mar 2011
    Posts
    51
    No Salem, that's not what I want. But its good to see the pause & alarm are working together!
    The idea is to have the parent print line after line for 5 seconds & pause, then the child print line after line for 5 seconds & pause, restarting the parent & looping like that continuously!

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Like this?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <wait.h>
    #include <signal.h>
    
    void handler( int );
    
    int main( void )
    {
        signal( SIGUSR1, handler );
        pid_t pid = fork();
        if( pid != 0 )
        {
            while( 1 )
            {
                printf( "[PARENT] Serving HTTP Session 2\n" );
                fflush( stdout );
                sleep(5);
                kill(pid,SIGUSR1);
                pause();
            }
        }
        else
        {
            pause();            // wait for first signal from parent
            pid = getppid();    // this is child, get the parent
            while( 1 )
            {
                printf( "[CHILD] Serving HTTP Session 1\n" );
                fflush( stdout );
                sleep(5);
                kill(pid,SIGUSR1);
                pause();
            }
        }
        exit( EXIT_SUCCESS );
    }
    
    /////////////////////////////////////////////////////////////////
    
    
    
    // Sub-function Implementation //////////////////////////////////
    
    void handler( int SIG )
    {
        printf( "[HANDLER] Signal received in process %d\n", (int)getpid() );
        fflush( stdout );
        signal( SIGUSR1, handler );
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User JM1082's Avatar
    Join Date
    Mar 2011
    Posts
    51
    No... still not quite right, but I like the way you've used the kill( pid ) thing! The messages are printing one at a time rather than very quickly, repeatedly until the process change... not far off though!

  10. #10
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Have you found already a solution?

    The reason why your initial approach doesn't work is that after fork() both processes are independent from each other and thus don't see the alarm call from the other (both will pause infinitely after the reach the signal handler the first time). alarm() only signals a SIGALRM to the calling process.
    You need some kind of interprocess communication between both processes.

    Quote Originally Posted by JM1082 View Post
    The idea is to have the parent print line after line for 5 seconds & pause, then the child print line after line for 5 seconds & pause, restarting the parent & looping like that continuously!
    How about that (I use one second cycles to make the effect more distinct):
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
     
    void wake_up(int sig);
    void alarm_handler(int sig);
     
    int active;    
    pid_t child_pid, parent_pid;
     
    int main(void)
    {
        char *output;
    
        signal(SIGALRM, alarm_handler);
        signal(SIGUSR1, wake_up);
        alarm(1);
    
        parent_pid = getpid();
        if((child_pid = fork()) != 0)
        {
            output = "[PARENT] Serving HTTP Session 2";
            active = 1;         // parent starts being active
        }
        else
        {
            output = "[CHILD] Serving HTTP Session 1";
            active = 0;         // child starts being inactive
        }
        
        while(1)
            if(active)
                puts(output);
    
        exit(EXIT_SUCCESS);
    }
     
    void alarm_handler(int sig)
    {
        pid_t my_pid = getpid();    // get pid from current process
        active = 0;                 // inactivate current process
    //  signal(SIGALRM, alarm_handler); // depending on your system you may have to reestablish the signal handler
        if (my_pid == parent_pid)
            kill(child_pid, SIGUSR1);   // "wake up" child
        else 
            kill(parent_pid, SIGUSR1);  // "wake up" parent
    }
    
    void wake_up(int sig)
    {
    //  signal(SIGUSR1, wake_up);  // depending on your system you may have to reestablish the signal handler
        alarm(1);       // start new cycle
        active = 1;     // activate called process
    }
    BTW: signal() should be replaced by sigaction() for more portable programs.

    Bye, Andreas

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 12-18-2010, 02:34 PM
  2. Correct usage of malloc and free for 2D array
    By disruptivetech in forum C Programming
    Replies: 1
    Last Post: 10-20-2008, 05:20 AM
  3. Correct usage of malloc()
    By cboard_member in forum C++ Programming
    Replies: 9
    Last Post: 07-24-2005, 06:28 AM
  4. Simple Question on Correct Usage of memset
    By deadpoet in forum C++ Programming
    Replies: 2
    Last Post: 03-16-2004, 08:58 AM
  5. Simple Calculator: Not Positive About Correct Usage of C++
    By Code-Disciple in forum C++ Programming
    Replies: 6
    Last Post: 03-20-2003, 03:17 PM