Skip to content

Instantly share code, notes, and snippets.

@ubergeek42
Created May 30, 2016 03:00
Show Gist options
  • Save ubergeek42/c2746dc68845adb40e6faf8f2c6b8192 to your computer and use it in GitHub Desktop.
Save ubergeek42/c2746dc68845adb40e6faf8f2c6b8192 to your computer and use it in GitHub Desktop.
Use splice() instead of read/write
commit 93c82634c1218feb191efcf64565582e97dd0fc5
Author: Keith Johnson <kj@ubergeek42.com>
Date: Sun May 29 23:00:08 2016 -0400
Use splice() instead of read()/write() in runguard
diff --git a/judge/runguard.c b/judge/runguard.c
index d0154c4..4ca6a9b 100644
--- a/judge/runguard.c
+++ b/judge/runguard.c
@@ -763,7 +763,7 @@ int main(int argc, char **argv)
double tmpd;
size_t data_read[3];
size_t data_passed[3];
- ssize_t nread, nwritten;
+ ssize_t nread;
char str[256];
struct itimerval itimer;
@@ -1115,30 +1115,50 @@ int main(int argc, char **argv)
for(i=1; i<=2; i++) {
if ( child_pipefd[i][PIPE_OUT] != -1 &&
FD_ISSET(child_pipefd[i][PIPE_OUT],&readfds) ) {
- nread = read(child_pipefd[i][PIPE_OUT], buf, BUF_SIZE);
- if ( nread==-1 ) error(errno,"reading child fd %d",i);
+
+ if (data_passed[i] == streamsize) {
+ /* Throw away data if we're done */
+ nread = read(child_pipefd[i][PIPE_OUT], buf, BUF_SIZE);
+ } else {
+ /* Otherwise copy it to the file */
+ nread = splice(child_pipefd[i][PIPE_OUT], NULL,
+ child_redirfd[i], NULL,
+ BUF_SIZE, SPLICE_F_MOVE);
+ data_passed[i] += nread;
+ }
+ if ( nread==-1 ) {
+ if (errno == EINTR ) continue;
+ error(errno,"copying data fd %d",i);
+ }
if ( nread==0 ) {
- /* EOF detected: close fd and indicate this with -1 */
- if ( close(child_pipefd[i][PIPE_OUT])!=0 ) {
- error(errno,"closing pipe for fd %d",i);
- }
- child_pipefd[i][PIPE_OUT] = -1;
- continue;
+ if (errno == EAGAIN || errno == EWOULDBLOCK) continue;
+ // EOF detected: close fd and indicate this with -1
+ if ( close(child_pipefd[i][PIPE_OUT])!=0 ) {
+ error(errno,"closing pipe for fd %d",i);
+ }
+ child_pipefd[i][PIPE_OUT] = -1;
+ continue;
}
data_read[i] += nread;
- if ( limit_streamsize && data_passed[i]+nread>=streamsize ) {
- if ( data_passed[i]<streamsize ) {
- verbose("child fd %d limit reached",i);
- }
- nread = streamsize - data_passed[i];
+
+ /* Truncate to the output limit */
+ if (limit_streamsize && data_passed[i] > streamsize) {
+ verbose("child fd %i limit reached",i);
+ data_passed[i] = streamsize;
+
+ ret = ftruncate(child_redirfd[i], streamsize);
+ if( ret!=0 ) error(errno,"truncating output fd %d", i);
}
- nwritten = write(child_redirfd[i], buf, nread);
- if ( nwritten==-1 ) error(errno,"writing child fd %d",i);
- data_passed[i] += nwritten;
}
}
}
+ /* Close the output files */
+ for(i=1; i<=2; i++) {
+ ret = close(child_redirfd[i]);
+ if( ret!=0 ) error(errno,"closing output fd %d", i);
+ }
+
if ( times(&endticks)==(clock_t) -1 ) {
error(errno,"getting end clock ticks");
}
@ubergeek42
Copy link
Author

https://gist.github.com/ubergeek42/c2746dc68845adb40e6faf8f2c6b8192#file-readwrite-splice-patch-L48 maybe should also check for EINTR, as I mentioned on IRC it isn't clear to me what the return value is when various things like that could occur.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment