Created
May 30, 2016 03:00
-
-
Save ubergeek42/c2746dc68845adb40e6faf8f2c6b8192 to your computer and use it in GitHub Desktop.
Use splice() instead of read/write
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 93c82634c1218feb191efcf64565582e97dd0fc5 | |
Author: Keith Johnson <[email protected]> | |
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"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.