The signal interrupts the send method in blocking mode

I am programming with a socket which is in blocking mode, I have a question about the method send

.

From the method man page send

, it says:

[EINTR] Signal interrupts the system call before sending any data.

This means that if the signal interrupts the system call before any data is sent, it send

will return -1 and errno

will be set to EINTR

.

My question is, if a piece of data has been transferred when the signal interrupts the system call, what will be returned. It seems like it shouldn't return -1 because it sent some data. I think it will return the amount of data passed, which means that a method send

in blocking mode can return less data than you passed in as the third parameter.

ssize_t send(int socket, const void *buffer, size_t length, int flags);

+3


source to share


3 answers


The other answers are pretty clear, but after reading some of your comments, I would like to add more information.

First of all, you are wrong in the idea EINTR

. Interrupting the signal in syscall is not considered an error. Justification EINTR

in slow system costs (slow system calls - those that can be blocked permanently, for example open(2)

for certain file types - for example, terminal devices - accept(2)

, read(2)

and write(2)

on some devices - includes sockets - and so on) is that if your program was blocked in syscall and the signal was caught (although still blocked), then it is very likely (but not necessary) that the signal handler changed state in your program, and things are different, so the call returns prematurely with EINTR

to give you the ability to do anything that you might want to do. It is not a mistake likeEINVAL

or EBADF

or other "real" bugs are how the kernel tells you that a signal has been caught.

If you don't want to do anything, either set the flag SA_RESTART

in the box sa_flags

struct sigaction

when setting up the signal handler (which causes the syscall to automatically restart), or explicitly call send(2)

again when it returns -1s errno

set to EINTR

.



The bottom line is that the kernel does not have an inherent limitation that makes it return to user space when signals are caught. Instead, EINTR

it is just convenient behavior that developers might find useful.

If the kernel was in the middle of a data transfer and a signal was raised, it doesn't really matter: if data is transferred, syscall makes progress. The kernel is in the context of a process executing syscall on behalf of the called program, so technically the process no longer sleeps. If a signal arrives, it will be postponed until the kernel decides it is time to deliver it to the process - most likely after returning send(2)

.

+2


source


The documentation is clear.

RETURN VALUE

If successful, these calls return the number of bytes sent. On error, -1 is returned and errno is set appropriately.

[...]

EINTR The signal occurred before any data was transmitted;

send()

returns

  • number of bytes sent
  • or -1



If returned -1

, the reason is specified via value errno

.

If errno

equal EINTR

, the signal is interrupted send()

and no data has been received .

From this information above, we can safely conclude that if the data had been received, the function send()

would not have returned -1

, no matter whether the signal was received or not.

+2


source


[EINTR] Signal interrupts the system call before sending any data.

This means that if you send()

start a data transfer, it will not be interrupted by any signals. Thus, the transmission will block the reception of the signal until it is completed. A situation where send()

fewer bytes of data may be returned than you passed as the third parameter is usually related to network problems such as dropped packets.

-1


source







All Articles