rbx.cp 0.5.72__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. rbx/annotations.py +21 -1
  2. rbx/box/cli.py +24 -8
  3. rbx/box/code.py +140 -3
  4. rbx/box/contest/build_contest_statements.py +44 -34
  5. rbx/box/contest/contest_utils.py +25 -0
  6. rbx/box/contest/main.py +24 -0
  7. rbx/box/contest/schema.py +52 -8
  8. rbx/box/contest/statements.py +53 -25
  9. rbx/box/download.py +19 -1
  10. rbx/box/fields.py +35 -0
  11. rbx/box/lang.py +27 -0
  12. rbx/box/package.py +1 -1
  13. rbx/box/packaging/boca/packager.py +48 -5
  14. rbx/box/packaging/contest_main.py +13 -0
  15. rbx/box/packaging/main.py +13 -2
  16. rbx/box/packaging/packager.py +4 -4
  17. rbx/box/packaging/pkg/packager.py +142 -0
  18. rbx/box/packaging/polygon/packager.py +2 -24
  19. rbx/box/packaging/polygon/upload.py +35 -17
  20. rbx/box/remote.py +2 -2
  21. rbx/box/schema.py +68 -18
  22. rbx/box/solutions.py +6 -1
  23. rbx/box/statements/build_statements.py +44 -27
  24. rbx/box/statements/builders.py +18 -10
  25. rbx/box/statements/expander.py +49 -0
  26. rbx/box/statements/latex_jinja.py +61 -4
  27. rbx/box/statements/schema.py +33 -9
  28. rbx/box/testcase_utils.py +19 -47
  29. rbx/box/tooling/__init__.py +0 -0
  30. rbx/box/tooling/boca/__init__.py +0 -0
  31. rbx/box/tooling/boca/main.py +13 -0
  32. rbx/box/tooling/boca/scrape.py +34 -0
  33. rbx/box/{packaging/boca/upload.py → tooling/boca/scraper.py} +77 -8
  34. rbx/box/tooling/main.py +8 -0
  35. rbx/box/ui/screens/run_explorer.py +1 -1
  36. rbx/box/ui/widgets/interaction_box.py +19 -1
  37. rbx/grading/caching.py +18 -2
  38. rbx/grading/judge/sandbox.py +48 -5
  39. rbx/grading/judge/sandboxes/isolate.py +1 -0
  40. rbx/grading/judge/sandboxes/stupid_sandbox.py +11 -5
  41. rbx/grading/judge/sandboxes/timeit.py +36 -15
  42. rbx/grading/processing_context.py +62 -78
  43. rbx/grading/steps.py +91 -40
  44. rbx/resources/packagers/boca/checker.sh +4 -1
  45. rbx/resources/packagers/boca/compile/c +2 -6
  46. rbx/resources/packagers/boca/compile/cc +2 -6
  47. rbx/resources/packagers/boca/compile/cpp +2 -6
  48. rbx/resources/packagers/boca/compile/java +1 -6
  49. rbx/resources/packagers/boca/compile/kt +24 -28
  50. rbx/resources/packagers/boca/compile/py2 +2 -6
  51. rbx/resources/packagers/boca/compile/py3 +2 -6
  52. rbx/resources/packagers/boca/interactive/c +15 -62
  53. rbx/resources/packagers/boca/interactive/cc +15 -62
  54. rbx/resources/packagers/boca/interactive/cpp +15 -61
  55. rbx/resources/packagers/boca/interactive/java +15 -67
  56. rbx/resources/packagers/boca/interactive/kt +15 -67
  57. rbx/resources/packagers/boca/interactive/py2 +15 -67
  58. rbx/resources/packagers/boca/interactive/py3 +15 -65
  59. rbx/resources/packagers/boca/interactor_compile.sh +5 -2
  60. rbx/resources/packagers/boca/interactor_run.sh +174 -0
  61. rbx/resources/packagers/boca/safeexec.c +530 -0
  62. rbx/resources/packagers/boca/safeexec_compile.sh +49 -0
  63. rbx/resources/presets/default/contest/contest.rbx.yml +9 -8
  64. rbx/resources/presets/default/problem/problem.rbx.yml +27 -26
  65. rbx/resources/templates/rbx.h +2 -3
  66. {rbx_cp-0.5.72.dist-info → rbx_cp-0.6.0.dist-info}/METADATA +2 -1
  67. {rbx_cp-0.5.72.dist-info → rbx_cp-0.6.0.dist-info}/RECORD +70 -59
  68. rbx/resources/packagers/boca/compile/pas +0 -172
  69. {rbx_cp-0.5.72.dist-info → rbx_cp-0.6.0.dist-info}/LICENSE +0 -0
  70. {rbx_cp-0.5.72.dist-info → rbx_cp-0.6.0.dist-info}/WHEEL +0 -0
  71. {rbx_cp-0.5.72.dist-info → rbx_cp-0.6.0.dist-info}/entry_points.txt +0 -0
@@ -61,6 +61,10 @@ fi
61
61
  # make sure that directories below are correct.
62
62
  sf=$(which safeexec)
63
63
  [ -x "$sf" ] || sf=/usr/bin/safeexec
64
+ if [ -x "../safeexec.exe" ]; then
65
+ cp "../safeexec.exe" "safeexec.exe"
66
+ sf="./safeexec.exe"
67
+ fi
64
68
 
65
69
  if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then
66
70
  echo "parameter problem"
@@ -90,8 +94,9 @@ if [ ! -x "$sf" ]; then
90
94
  fi
91
95
 
92
96
  time=$3
93
- if [ "$time" -gt "0" ]; then
94
- let "ttime = $time * 4"
97
+ rtime=$(awk "BEGIN {print int($time+0.9999999)}")
98
+ if [ "$rtime" -gt "0" ]; then
99
+ let "ttime = $rtime * 4"
95
100
  else
96
101
  time=1
97
102
  ttime=4
@@ -99,8 +104,8 @@ fi
99
104
 
100
105
  nruns=1
101
106
  if [ "$4" != "" ]; then
102
- if [ "$4" -gt "0" ]; then
103
- nruns=$4
107
+ if [ "$4" -gt "1" ]; then
108
+ echo "WARNING: nruns is set to $4, but it will be ignored because it's not supported by interactive problems"
104
109
  fi
105
110
  fi
106
111
  maxm=512000
@@ -124,58 +129,9 @@ cdir=$(pwd)
124
129
  echo "Current directory is $cdir -- chrooting on it" >&2
125
130
 
126
131
  ### START OF BOCA RUN COMMAND
127
- cat <<EOF >runit.sh
128
- #!/bin/bash
129
- mkfifo fifo.in fifo.out
130
-
131
- echo "Running solution as \$@" >&2
132
-
133
- "\$@" >fifo.out <fifo.in 2>/dev/null &
134
- SFPID=\$!
135
-
136
- ./interactor.exe "stdin0" "stdout0" <fifo.out >fifo.in 2>stderr0 &
137
- INTPID=\$!
138
-
139
- wait \$INTPID
140
- ECINT=\$?
141
-
142
- ECSF=0
143
- if [[ \$ECINT -ge 1 ]] && [[ \$ECINT -le 4 ]]; then
144
- # kill the solution
145
- kill -9 \$SFPID
146
- else
147
- wait \$SFPID
148
- ECSF=\$?
149
- fi
150
-
151
- rm -rf fifo.in fifo.out
152
-
153
- echo "Ran solution as \$@" &>>stderr0
154
- echo "interactor exitcode \$ECINT" &>>stderr0
155
- echo "solution exitcode \$ECSF" &>>stderr0
156
-
157
- RTE=0
158
- if [[ \$ECSF -eq -13 ]]; then
159
- RTE=0
160
- elif [[ \$ECSF -ne 0 ]] && cat stderr0 | grep -q "wrong output format Unexpected end of file"; then
161
- echo "Found EOF RTE" &>>stderr0
162
- RTE=1
163
- fi
164
-
165
- ret=0
166
- if [[ \$ECINT -ge 1 ]] && [[ \$ECINT -le 4 ]] && [[ \$RTE -eq 0 ]]; then
167
- echo "testlib exitcode \$ECINT" >stdout0
168
- ret=0
169
- elif [[ \$ECSF -ne 0 ]]; then
170
- ret=\$ECSF
171
- elif [[ \$ECINT -ne 0 ]]; then
172
- ret=9
173
- fi
174
-
175
- echo "exitting from runit.sh with exit code \$ret" &>>stderr0
176
- exit \$ret
132
+ cat >runit.sh <<"EOF"
133
+ {{runit_content}}
177
134
  EOF
178
-
179
135
  chmod 755 runit.sh
180
136
 
181
137
  ret=0
@@ -194,13 +150,14 @@ if [ $? -eq 0 ]; then
194
150
  exit 47
195
151
  fi
196
152
  export CLASSPATH=.:./run.jar:$CLASSPATH
197
- "$sf" -r$nruns -t$time -T$ttime -istdin0 -F512 -u512 -U$bocau -G$bocag -ostdout0 -estderr0 -n0 -C. -d40000000000 -m40000000000 -- "\$kotlin" -cp run.jar -J-Xmx${maxm}K -J-Xss${maxms}K -J-Xms${maxm}K "$name"
153
+ ./runit.sh "$cdir" "$sf" "$ttime" -r$nruns -t$time -T$ttime -F512 -u512 -U$bocau -G$bocag -n0 -C. -d40000000000 -m40000000000 -- "\$kotlin" -cp run.jar -J-Xmx${maxm}K -J-Xss${maxms}K -J-Xms${maxm}K "$name"
198
154
  retval=\$?
199
155
  echo \$retval > runch.exitcode
200
156
  if [ ! -d /bocajail ]; then
201
157
  /bin/umount /proc 2>/dev/null
202
158
  /bin/umount /sys 2>/dev/null
203
159
  fi
160
+ rm -rf fifo.in fifo.out
204
161
  EOF
205
162
  chmod 755 runch.sh
206
163
  chroot /bocajail $cdir/runch.sh
@@ -212,17 +169,8 @@ EOF
212
169
  exit 49
213
170
  fi
214
171
  else
215
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
216
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
217
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
218
- kotlin=$(which kotlin)
219
- [ -x "$kotlin" ] || kotlin=/usr/bin/kotlin
220
- if [ ! -x "$kotlin" ]; then
221
- echo "$kotlin not found or it's not executable"
222
- exit 47
223
- fi
224
- "$sf" -r$nruns -t$time -T$ttime -istdin0 -F512 -u512 -U$bocau -G$bocag -ostdout0 -estderr0 -n0 -C. -d40000000000 -m40000000000 -- "$kotlin" -cp run.jar -J-Xmx${maxm}K -J-Xss${maxms}K -J-Xms${maxm}K "$name"
225
- ret=$?
172
+ echo "ERROR: CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
173
+ exit 48
226
174
  fi
227
175
  ### END OF BOCA RUN COMMAND
228
176
 
@@ -61,6 +61,10 @@ fi
61
61
  # make sure that directories below are correct.
62
62
  sf=$(which safeexec)
63
63
  [ -x "$sf" ] || sf=/usr/bin/safeexec
64
+ if [ -x "../safeexec.exe" ]; then
65
+ cp "../safeexec.exe" "safeexec.exe"
66
+ sf="./safeexec.exe"
67
+ fi
64
68
 
65
69
  if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then
66
70
  echo "parameter problem"
@@ -77,8 +81,9 @@ if [ ! -x "$sf" ]; then
77
81
  fi
78
82
 
79
83
  time=$3
80
- if [ "$time" -gt "0" ]; then
81
- let "ttime = $time * 4"
84
+ rtime=$(awk "BEGIN {print int($time+0.9999999)}")
85
+ if [ "$rtime" -gt "0" ]; then
86
+ let "ttime = $rtime * 4"
82
87
  else
83
88
  time=1
84
89
  ttime=4
@@ -86,8 +91,8 @@ fi
86
91
 
87
92
  nruns=1
88
93
  if [ "$4" != "" ]; then
89
- if [ "$4" -gt "0" ]; then
90
- nruns=$4
94
+ if [ "$4" -gt "1" ]; then
95
+ echo "WARNING: nruns is set to $4, but it will be ignored because it's not supported by interactive problems"
91
96
  fi
92
97
  fi
93
98
  maxm=512000
@@ -111,58 +116,9 @@ cdir=$(pwd)
111
116
  echo "Current directory is $cdir -- chrooting on it" >&2
112
117
 
113
118
  ### START OF BOCA RUN COMMAND
114
- cat <<EOF >runit.sh
115
- #!/bin/bash
116
- mkfifo fifo.in fifo.out
117
-
118
- echo "Running solution as \$@" >&2
119
-
120
- "\$@" >fifo.out <fifo.in 2>/dev/null &
121
- SFPID=\$!
122
-
123
- ./interactor.exe "stdin0" "stdout0" <fifo.out >fifo.in 2>stderr0 &
124
- INTPID=\$!
125
-
126
- wait \$INTPID
127
- ECINT=\$?
128
-
129
- ECSF=0
130
- if [[ \$ECINT -ge 1 ]] && [[ \$ECINT -le 4 ]]; then
131
- # kill the solution
132
- kill -9 \$SFPID
133
- else
134
- wait \$SFPID
135
- ECSF=\$?
136
- fi
137
-
138
- rm -rf fifo.in fifo.out
139
-
140
- echo "Ran solution as \$@" &>>stderr0
141
- echo "interactor exitcode \$ECINT" &>>stderr0
142
- echo "solution exitcode \$ECSF" &>>stderr0
143
-
144
- RTE=0
145
- if [[ \$ECSF -eq -13 ]]; then
146
- RTE=0
147
- elif [[ \$ECSF -ne 0 ]] && cat stderr0 | grep -q "wrong output format Unexpected end of file"; then
148
- echo "Found EOF RTE" &>>stderr0
149
- RTE=1
150
- fi
151
-
152
- ret=0
153
- if [[ \$ECINT -ge 1 ]] && [[ \$ECINT -le 4 ]] && [[ \$RTE -eq 0 ]]; then
154
- echo "testlib exitcode \$ECINT" >stdout0
155
- ret=0
156
- elif [[ \$ECSF -ne 0 ]]; then
157
- ret=\$ECSF
158
- elif [[ \$ECINT -ne 0 ]]; then
159
- ret=9
160
- fi
161
-
162
- echo "exitting from runit.sh with exit code \$ret" &>>stderr0
163
- exit \$ret
119
+ cat >runit.sh <<"EOF"
120
+ {{runit_content}}
164
121
  EOF
165
-
166
122
  chmod 755 runit.sh
167
123
 
168
124
  ret=0
@@ -180,13 +136,14 @@ if [ $? -eq 0 ]; then
180
136
  echo "\$python2 not found or it's not executable"
181
137
  exit 47
182
138
  fi
183
- "$sf" -F256 -u256 -f$maxf -r$nruns -n0 -C. -U$bocau -G$bocag -d$maxm -m$maxm -t$time -T$ttime -ostdout0 -estderr0 -- ./runit.sh "\$python2" "$name"
139
+ ./runit.sh "$cdir" "$sf" "$ttime" -F256 -u256 -f$maxf -r$nruns -n0 -C. -U$bocau -G$bocag -d$maxm -m$maxm -t$time -T$ttime -- "\$python2" "$name"
184
140
  retval=\$?
185
141
  echo \$retval > runch.exitcode
186
142
  if [ ! -d /bocajail ]; then
187
143
  /bin/umount /proc 2>/dev/null
188
144
  /bin/umount /sys 2>/dev/null
189
145
  fi
146
+ rm -rf fifo.in fifo.out
190
147
  EOF
191
148
  chmod 755 runch.sh
192
149
  chroot /bocajail $cdir/runch.sh
@@ -198,17 +155,8 @@ EOF
198
155
  exit 49
199
156
  fi
200
157
  else
201
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
202
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
203
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
204
- python2=$(which python2)
205
- [ -x "$python2" ] || python2=/usr/bin/python2
206
- if [ ! -x "$python2" ]; then
207
- echo "$python2 not found or it's not executable"
208
- exit 47
209
- fi
210
- "$sf" -F256 -u256 -f$maxf -r$nruns -n0 -C. -U$bocau -G$bocag -d$maxm -m$maxm -t$time -T$ttime -ostdout0 -estderr0 -- ./runit.sh "$python2" "$name"
211
- ret=$?
158
+ echo "ERROR: CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
159
+ exit 48
212
160
  fi
213
161
  ### END OF BOCA RUN COMMAND
214
162
 
@@ -61,6 +61,10 @@ fi
61
61
  # make sure that directories below are correct.
62
62
  sf=$(which safeexec)
63
63
  [ -x "$sf" ] || sf=/usr/bin/safeexec
64
+ if [ -x "../safeexec.exe" ]; then
65
+ cp "../safeexec.exe" "safeexec.exe"
66
+ sf="./safeexec.exe"
67
+ fi
64
68
 
65
69
  if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then
66
70
  echo "parameter problem"
@@ -77,8 +81,9 @@ if [ ! -x "$sf" ]; then
77
81
  fi
78
82
 
79
83
  time=$3
80
- if [ "$time" -gt "0" ]; then
81
- let "ttime = $time * 4"
84
+ rtime=$(awk "BEGIN {print int($time+0.9999999)}")
85
+ if [ "$rtime" -gt "0" ]; then
86
+ let "ttime = $rtime * 4"
82
87
  else
83
88
  time=1
84
89
  ttime=4
@@ -86,8 +91,8 @@ fi
86
91
 
87
92
  nruns=1
88
93
  if [ "$4" != "" ]; then
89
- if [ "$4" -gt "0" ]; then
90
- nruns=$4
94
+ if [ "$4" -gt "1" ]; then
95
+ echo "WARNING: nruns is set to $4, but it will be ignored because it's not supported by interactive problems"
91
96
  fi
92
97
  fi
93
98
  maxm=512000
@@ -111,56 +116,9 @@ cdir=$(pwd)
111
116
  echo "Current directory is $cdir -- chrooting on it" >&2
112
117
 
113
118
  ### START OF BOCA RUN COMMAND
114
- cat <<EOF >runit.sh
115
- #!/bin/bash
116
- mkfifo fifo.in fifo.out
117
-
118
- "\$@" >fifo.out <fifo.in 2>/dev/null &
119
- SFPID=\$!
120
-
121
- ./interactor.exe "stdin0" "stdout0" <fifo.out >fifo.in 2>stderr0 &
122
- INTPID=\$!
123
-
124
- wait \$INTPID
125
- ECINT=\$?
126
-
127
- ECSF=0
128
- if [[ \$ECINT -ge 1 ]] && [[ \$ECINT -le 4 ]]; then
129
- # kill the solution
130
- kill -9 \$SFPID
131
- else
132
- wait \$SFPID
133
- ECSF=\$?
134
- fi
135
-
136
- rm -rf fifo.in fifo.out
137
-
138
- echo "Ran solution as \$@" &>>stderr0
139
- echo "interactor exitcode \$ECINT" &>>stderr0
140
- echo "solution exitcode \$ECSF" &>>stderr0
141
-
142
- RTE=0
143
- if [[ \$ECSF -eq -13 ]]; then
144
- RTE=0
145
- elif [[ \$ECSF -ne 0 ]] && cat stderr0 | grep -q "wrong output format Unexpected end of file"; then
146
- echo "Found EOF RTE" &>>stderr0
147
- RTE=1
148
- fi
149
-
150
- ret=0
151
- if [[ \$ECINT -ge 1 ]] && [[ \$ECINT -le 4 ]] && [[ \$RTE -eq 0 ]]; then
152
- echo "testlib exitcode \$ECINT" >stdout0
153
- ret=0
154
- elif [[ \$ECSF -ne 0 ]]; then
155
- ret=\$ECSF
156
- elif [[ \$ECINT -ne 0 ]]; then
157
- ret=9
158
- fi
159
-
160
- echo "exitting from runit.sh with exit code \$ret" &>>stderr0
161
- exit \$ret
119
+ cat >runit.sh <<"EOF"
120
+ {{runit_content}}
162
121
  EOF
163
-
164
122
  chmod 755 runit.sh
165
123
 
166
124
  ret=0
@@ -178,13 +136,14 @@ if [ $? -eq 0 ]; then
178
136
  echo "\$python3 not found or it's not executable"
179
137
  exit 47
180
138
  fi
181
- "$sf" -F256 -u256 -f$maxf -r$nruns -n0 -C. -U$bocau -G$bocag -d$maxm -m$maxm -t$time -T$ttime -ostdout0 -estderr0 -- ./runit.sh "\$python3" "$name"
139
+ ./runit.sh "$cdir" "$sf" "$ttime" -F256 -u256 -f$maxf -r$nruns -n0 -C. -U$bocau -G$bocag -d$maxm -m$maxm -t$time -T$ttime -- "\$python3" "$name"
182
140
  retval=\$?
183
141
  echo \$retval > runch.exitcode
184
142
  if [ ! -d /bocajail ]; then
185
143
  /bin/umount /proc 2>/dev/null
186
144
  /bin/umount /sys 2>/dev/null
187
145
  fi
146
+ rm -rf fifo.in fifo.out
188
147
  EOF
189
148
  chmod 755 runch.sh
190
149
  chroot /bocajail $cdir/runch.sh
@@ -196,17 +155,8 @@ EOF
196
155
  exit 49
197
156
  fi
198
157
  else
199
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
200
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
201
- echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
202
- python3=$(which python3)
203
- [ -x "$python3" ] || python3=/usr/bin/python3
204
- if [ ! -x "$python3" ]; then
205
- echo "$python3 not found or it's not executable"
206
- exit 47
207
- fi
208
- "$sf" -F256 -u256 -f$maxf -r$nruns -n0 -C. -U$bocau -G$bocag -d$maxm -m$maxm -t$time -T$ttime -ostdout0 -estderr0 -- ./runit.sh "$python3" "$name"
209
- ret=$?
158
+ echo "ERROR: CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2
159
+ exit 48
210
160
  fi
211
161
  ### END OF BOCA RUN COMMAND
212
162
 
@@ -1,4 +1,7 @@
1
1
  ### START OF INTERACTOR COMPILATION
2
+ CACHE_DIR="/tmp/boca-cache"
3
+ mkdir -p $CACHE_DIR
4
+
2
5
  # Assumes testlib was added by checker
3
6
  INTERACTOR_PATH="interactor.cpp"
4
7
  INTERACTOR_OUT="interactor.exe"
@@ -21,8 +24,8 @@ EOF
21
24
 
22
25
  printf "%s" "${InteractorContent}" >$INTERACTOR_PATH
23
26
 
24
- interactor_hash=($(md5sum $INTERACTOR_PATH))
25
- interactor_cache="/tmp/boca-int-${interactor_hash}"
27
+ interactor_hash=($(cat $INTERACTOR_PATH rbx.h testlib.h | md5sum))
28
+ interactor_cache="$CACHE_DIR/interactor-${interactor_hash}"
26
29
 
27
30
  echo "Interactor hash: $interactor_hash"
28
31
  echo "Copying interactor to $CDIR/$INTERACTOR_OUT"
@@ -0,0 +1,174 @@
1
+ #!/bin/bash
2
+ # $1 is cdir
3
+ # $2 is sf
4
+
5
+ cdir=$1
6
+ shift
7
+ sf=$1
8
+ shift
9
+ ttime=$1
10
+ shift
11
+
12
+ # Add 1 second to the wall TL of the interactor to be safe.
13
+ ittime=$(($ttime + 1))
14
+
15
+ cd "$cdir"
16
+
17
+ # Ensure fifos are created and given access to.
18
+ mkfifo fifo.in fifo.out
19
+ chmod 666 fifo.in fifo.out
20
+ chown nobody fifo.in fifo.out
21
+
22
+ # Ensure interactor's side input and output can't be read by solution.
23
+ touch stdin0 stdout0 interactor.stderr
24
+ chmod 640 stdin0 stdout0 interactor.stderr
25
+
26
+ echo "Running solution with safeexec params $@" >&2
27
+
28
+ # Execute interactor in a memory-limited shell to ensure a misbehaved interactor
29
+ # doesn't starve the system.
30
+ cat >runit_wrapper.sh <<"WRAPPERFOF"
31
+ #!/bin/bash
32
+ # SIGTERM after ttime, SIGKILL after extra 5 seconds.
33
+ (sleep $1; kill -TERM -$$; sleep 5; kill -9 -$$) 2>/dev/null &
34
+ ulimit -v 1024000 && exec ./interactor.exe "stdin0" "stdout0"
35
+ exit $?
36
+ WRAPPERFOF
37
+ chmod 755 runit_wrapper.sh
38
+ ./runit_wrapper.sh $ittime <fifo.out >fifo.in 2>interactor.stderr &
39
+ INTPID=$!
40
+
41
+ "$sf" -ofifo.out -ififo.in "$@" 2>safeexec.sf.stderr &
42
+ SFPID=$!
43
+
44
+ ECINT=0
45
+ ECSF=0
46
+
47
+ echo "interactor pid $INTPID" >>stderr0
48
+ echo "solution pid $SFPID" >>stderr0
49
+
50
+ wait -p EXITID -n $SFPID $INTPID
51
+ ECEXIT=$?
52
+ if [[ $ECEXIT -ne 0 ]]; then
53
+ kill -SIGTERM $SFPID $INTPID 2>/dev/null
54
+ fi
55
+
56
+ EXITFIRST=none
57
+ if [[ $EXITID -eq $INTPID ]]; then
58
+ # In case the interactor exits first, we can just wait for the solution to finish.
59
+ # It will certainly finish at some point since it's running inside a constrained
60
+ # safeexec environment.
61
+ wait $SFPID
62
+ ECSF=$?
63
+ ECINT=$ECEXIT
64
+ EXITFIRST=interactor
65
+ else
66
+ # When solution exits first, we're sure that it ACTUALLY finished first.
67
+ # So, in case of non-zero exit code, we probably already halted the interactor.
68
+ # Otherwise, let's wait for it for a maximum of wall time and then halt it to ensure
69
+ # a misbehaved interactor doesn't hang the entire judge.
70
+ wait $INTPID
71
+ ECINT=$?
72
+ ECSF=$ECEXIT
73
+ EXITFIRST=solution
74
+ fi
75
+
76
+ echo "interactor exitcode $ECINT" >>stderr0
77
+ echo "solution exitcode $ECSF" >>stderr0
78
+ echo "exit first $EXITFIRST" >>stderr0
79
+
80
+ # Recover permissions.
81
+ chmod 644 stdin0 stdout0
82
+
83
+ # SAFEEXEC STDERR
84
+ echo "== <safeexec solution stderr> ==" >>stderr0
85
+ cat safeexec.sf.stderr >>stderr0
86
+ echo "== </safeexec solution stderr> ==" >>stderr0
87
+
88
+ # INTERACTOR STDERR
89
+ echo "== <interactor stderr> ==" >>stderr0
90
+ cat interactor.stderr >>stderr0 2>/dev/null
91
+ echo "== </interactor stderr> ==" >>stderr0
92
+ ###
93
+
94
+ JUDGE_ERROR=4
95
+ finish() {
96
+ echo "exitting from runit.sh with exit code $1" >>stderr0
97
+ rm -rf fifo.in fifo.out
98
+ exit $1
99
+ }
100
+
101
+ # Solution RTE, for checking purposes, is defined as any safeexec non-zero exit code, except for TLE or MLE.
102
+ is_solution_rte() {
103
+ if [[ $1 -eq 0 ]]; then
104
+ false
105
+ return
106
+ fi
107
+
108
+ # In case of TLE or MLE, we don't consider as RTE.
109
+ if [[ $1 -eq 3 ]] || [[ $1 -eq 7 ]]; then
110
+ false
111
+ return
112
+ fi
113
+ true
114
+ }
115
+
116
+ # Interactor RTE, for checking purposes, is defined as any non-zero exit code, except for SIGTERM or SIGPIPE, or exit codes
117
+ # reserved for testlib.
118
+ is_interactor_rte() {
119
+ if [[ $1 -eq 0 ]] || [[ $1 -eq 143 ]] || [[ $1 -eq 141 ]]; then
120
+ false
121
+ return
122
+ fi
123
+
124
+ if [[ $1 -ge 1 ]] && [[ $1 -le 4 ]]; then
125
+ false
126
+ return
127
+ fi
128
+
129
+ true
130
+ }
131
+
132
+ # Check for interactor errors.
133
+ check_interactor() {
134
+ local EC=$ECINT
135
+ if [[ $EC -eq 0 ]]; then
136
+ return
137
+ fi
138
+
139
+ if [[ $EC -ge 1 ]] && [[ $EC -le 4 ]]; then
140
+ echo "testlib returned WA-like exitcode $EC" >>stderr0
141
+ echo "testlib exitcode $EC" >stdout0
142
+ finish 0
143
+ fi
144
+
145
+ finish $JUDGE_ERROR
146
+ }
147
+
148
+ # 0. Interactor has crashed?
149
+ if is_interactor_rte $ECINT; then
150
+ echo "interactor EXITED WITH NON-ZERO CODE $ECINT" >>stderr0
151
+ finish $JUDGE_ERROR
152
+ fi
153
+
154
+ # 1. Solution has exceed limits?
155
+ if [[ $ECSF -eq 3 ]] || [[ $ECSF -eq 7 ]]; then
156
+ finish $ECSF
157
+ fi
158
+
159
+ # 2. Check for interactor errors.
160
+ # TODO: Maybe one day get rid of "wrong output format" check with extra fifos.
161
+ if ([[ $EXITFIRST == "interactor" ]] || is_solution_rte $ECSF) && ! cat stderr0 | grep -q "wrong output format Unexpected end of file"; then
162
+ check_interactor
163
+ fi
164
+
165
+ # 3. Check for solution errors.
166
+ if [[ $ECSF -ne 0 ]]; then
167
+ finish $ECSF
168
+ fi
169
+
170
+ # 4. Check for interactor without looking at solution output.
171
+ check_interactor
172
+
173
+ # 5. Finish with zero and later check output.
174
+ finish 0