0

I want to drain a pipe by pushing all its data to a socket using the splice system call on Linux.

My current attempt is:

ssize_t splice(int i, loff_t* io, int o, loff_t* oo, size_t l, unsigned int flags);
int  spliceAll(int i, loff_t* io, int o, loff_t* oo, size_t l, unsigned int flags) {
  size_t t =  0; int n = 0;
  while (t <  l) { if ((n = splice(i, io, o, oo, l - t, flags)) < 0) break; t += n; }
  return t == l ? 0 : -1;
}

the user-space buffer equivalent to this is is simply:

int sendAll(int s, void* b, size_t l, int flags) {
  size_t t =  0; int n = 0;
  while (t <  l) { if ((n = send(s, b + t, l - t, flags)) < 0) break; t += n; }
  return t == l ? 0 : -1;
}

Assuming non-blocking sockets (and pipes for spliceAll) AND send & splice never returning 0:

  • Is the loop in spliceAll correct?

  • Are there any other errors I am failing to see in both spliceAll and sendAll?
Cetin Sert
  • 4,497
  • 5
  • 38
  • 76
  • 1
    if send() happens to return zero, you;ll loop forever. – wildplasser Feb 12 '13 at 00:06
  • @wildplasser what does it mean for `send` to return `0`? is it the same as `recv` returning `0`, which means the socket is closed? – Cetin Sert Feb 12 '13 at 00:15
  • manpage from write(2) : `RETURN VALUE On success, the number of bytes written is returned (zero indicates nothing was written).` (I don't know the value of flags, but IMHO you **should** be prepared for send() to return zero) I guess send could return zero if for instance the link is broken and the buffers are already filled to the rim. – wildplasser Feb 12 '13 at 00:20
  • @wildplasser according to this http://stackoverflow.com/questions/3081952/with-c-tcp-sockets-can-send-return-zero I can just keep sending until I encounter `-1`. Thanks for pointing out the infinite loop possibility! – Cetin Sert Feb 12 '13 at 00:20
  • 1
    Yes, but you'd still loop like a madman (untill the connection times out, or is reestablished), spending 100% CPU on system calls. Just face it: zero is a valid return value for send() or write() You should handle it (or avoid it by using non-blocking mode and handling EWOULDBLOCK, and maybe others) – wildplasser Feb 12 '13 at 00:23
  • @wildplasser Oh I am using non-blocking sockets but using an epoll state machine this madman situation can only be handled outside `sendAll`/`spliceAll`, waiting for `EPOLLOUT` events once `send` or its equivalents encounter `EWOULDBLOCK | ..` and where to store the accumulating data until `EPOLLOUT`? Hmm o_O. – Cetin Sert Feb 12 '13 at 00:36
  • Not enough information. Maybe should compose a *complete* question and ask that instead ? – wildplasser Feb 12 '13 at 00:38
  • 1
    @wildplasser I believe this question has enough valuable information as it stands thanks to your comments. I cannot formulate a more complete question for the time being. – Cetin Sert Feb 12 '13 at 00:42

0 Answers0