Thread: recvfrom getting : Interrupted system call

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    569

    recvfrom getting : Interrupted system call

    when I tried to perform recvfrom using the code below:

    Code:
    flag = sigprocmask(SIG_SETMASK, &oset, NULL);
    			if (flag != 0 && flag == -1){
    				perror("Error: Unblocking alarm failed \n");
    				close(sock_fd);
    				exit(1);
    			}
    
    
    Frame *ACK = (Frame*) malloc(sizeof(Frame));
    		flag = recvfrom(sock_fd, ACK, sizeof(Frame), 0,  (struct sockaddr *) 0, (socklen_t *) 0);
    		if (flag == -1)
    		{
    			perror("Error: Receiving ACK failed \n");
    			close(sock_fd);
    			exit(1);
    		}
    I got an "Interrupted system call" error. Before this I have the unblocked SIGALARM, is this the reason why? Is there a way to keep SIGALARM unblocked and not receiving this error when calling recvfrom?

  2. #2
    Registered User Maz's Avatar
    Join Date
    Nov 2005
    Location
    Finland
    Posts
    194
    Many of the blocking IO calls in linux may be interrupted by signals. If I interpreted your question correctly, that is what happened. I guess usual way to deal with interrupted blocking calls is to continue waiting the remaining wait time. I assume you have read the man pages?

  3. #3
    Registered User
    Join Date
    Jan 2008
    Posts
    569
    And how can I do that??

  4. #4
    Registered User Maz's Avatar
    Join Date
    Nov 2005
    Location
    Finland
    Posts
    194
    I guess errno will have EINTR set, if recfrom was interrupted by a signal. Usually you check if that is the case, and if it is, you'll perform the same I/O call again. (If call accepts timeout [can't remember if recvfrom does], you should decrement the timeout by already elapsed time.) If there was data coming in, next call will collect the remaining data.

    Or then I misinterpreted your question.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    System call interruption is not an error (although it's reported like one). You must restart the system call. The general idiom is:

    Code:
    int err;
    
    while((err = syscall(...)) < 0 && errno == EINTR)
        ;
    if(err < 0)
        handle_error();
    In this specific case, you should probably change your timeout to account for the time already spent.

    If you treat syscall interruption as an error, your code is semantically wrong. You could receive a harmless signal at any time. And debuggers use signals to control processes, so running your program under a debugger could break, if you do not handle this correctly.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Registered User
    Join Date
    Jan 2008
    Posts
    569
    What if instead of checking the flag I also check for system call interruption, if thats the case then it shouldn't go inside the body?

  7. #7
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Ok, I have a question as well about this subject. I've always found this strange. I always test for EINTR, but I never really knew why such a call would not simply continue after an signal. Is it specifically for this reason, to set a timeout? Because for something like that you could just use select().
    There must be a really good reason. I just don't know it. Any ideas, anyone?

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by -EquinoX- View Post
    What if instead of checking the flag I also check for system call interruption, if thats the case then it shouldn't go inside the body?
    You have to check the return value first. The value of errno is not valid unless a system call has failed. So you have to check both.

    And just treating it as if the call succeeded isn't right, either. The call didn't fail or succeed, it just never FINISHED. You can't continue doing things until you know whether it failed or succeeded -- you must restart
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Registered User
    Join Date
    Jan 2008
    Posts
    569
    so I should check what recvfrom returns right? if it's -1 then I should also check for the errno... then what do I do? what do you mean by restart? won't restarting it have the same effect? i.e: will return the system call interrupted

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by -EquinoX- View Post
    so I should check what recvfrom returns right? if it's -1 then I should also check for the errno... then what do I do? what do you mean by restart? won't restarting it have the same effect? i.e: will return the system call interrupted
    You should do pretty much what I indicated in the example code.

    Restarting the call will not be interrupted again unless a second signal is delivered. In theory, it could happen, but you just need to keep looping until it is not interrupted.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  11. #11
    Registered User
    Join Date
    Jan 2008
    Posts
    569
    what should be the ...

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by -EquinoX- View Post
    what should be the ...
    syscall(...) stands in for whatever system call you are performing. In this case, it's your call to recvfrom()

    EDIT: Maybe this is a dumb question, but why are you using SIGALRM? Are you trying to implement a timeout for recvfrom()? Because if so, that changes everything.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  13. #13
    Registered User
    Join Date
    Jan 2008
    Posts
    569
    Quote Originally Posted by brewbuck View Post
    syscall(...) stands in for whatever system call you are performing. In this case, it's your call to recvfrom()

    EDIT: Maybe this is a dumb question, but why are you using SIGALRM? Are you trying to implement a timeout for recvfrom()? Because if so, that changes everything.
    so it would be:

    Code:
    while((err = syscall(recvfrom(sock_fd, ACK, sizeof(Frame), 0,  (struct sockaddr *) 0, (socklen_t *) 0))) < 0 && errno == EINTR)
    the reason I have an alarm here is to call a function, which is not recvfrom, every 100ms. Before this recvfrom I unblock the sigalarm so that it can call that function every 100ms. It's not to call recvfrom every 100ms

  14. #14
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by -EquinoX- View Post
    so it would be:

    Code:
    while((err = syscall(recvfrom(sock_fd, ACK, sizeof(Frame), 0,  (struct sockaddr *) 0, (socklen_t *) 0))) < 0 && errno == EINTR)
    No... the "syscall" part was just a stand-in for your actual system call. Other than that, you're correct.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  15. #15
    Registered User
    Join Date
    Jan 2008
    Posts
    569
    ok I think I got it.. whats EINTR?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 03-05-2009, 10:25 AM
  2. Inline asm
    By brietje698 in forum C++ Programming
    Replies: 5
    Last Post: 11-11-2007, 02:54 PM
  3. nanosleep() -system call does some confusing things
    By jtk in forum Linux Programming
    Replies: 5
    Last Post: 08-30-2007, 04:15 AM
  4. temperature sensors
    By danko in forum C Programming
    Replies: 22
    Last Post: 07-10-2007, 07:26 PM
  5. Pls help me to do this project in C I need source code
    By sureshmenon74 in forum C Programming
    Replies: 4
    Last Post: 10-04-2001, 06:57 AM