5353#include "src/common/libeventlog/eventlog.h"
5454#include "src/common/libeventlog/eventlogger.h"
5555#include "src/common/libioencode/ioencode.h"
56+ #include "src/common/libutil/parse_size.h"
5657#include "ccan/str/str.h"
5758
5859#include "task.h"
6162#include "builtins.h"
6263#include "log.h"
6364
64- #define OUTPUT_LIMIT_BYTES 1024*1024*10
65- #define OUTPUT_LIMIT_STRING "10MB"
65+ #define MULTIUSER_OUTPUT_LIMIT "10M"
6666
6767enum {
6868 FLUX_OUTPUT_TYPE_TERM = 1 ,
@@ -82,6 +82,8 @@ struct shell_output_type_file {
8282
8383struct shell_output {
8484 flux_shell_t * shell ;
85+ const char * kvs_limit_string ;
86+ size_t kvs_limit_bytes ;
8587 struct eventlogger * ev ;
8688 double batch_timeout ;
8789 int refcount ;
@@ -341,6 +343,9 @@ static bool check_kvs_output_limit (struct shell_output *out,
341343 size_t * bytesp ;
342344 size_t prev ;
343345
346+ if (out -> kvs_limit_bytes == 0 )
347+ return false;
348+
344349 if (is_stdout ) {
345350 stream = "stdout" ;
346351 bytesp = & out -> stdout_bytes ;
@@ -353,13 +358,13 @@ static bool check_kvs_output_limit (struct shell_output *out,
353358 prev = * bytesp ;
354359 * bytesp += len ;
355360
356- if (* bytesp > OUTPUT_LIMIT_BYTES ) {
361+ if (* bytesp > out -> kvs_limit_bytes ) {
357362 /* Only log an error when the threshold is reached.
358363 */
359- if (prev <= OUTPUT_LIMIT_BYTES )
364+ if (prev <= out -> kvs_limit_bytes )
360365 shell_warn ("%s will be truncated, %s limit exceeded" ,
361366 stream ,
362- OUTPUT_LIMIT_STRING );
367+ out -> kvs_limit_string );
363368 return true;
364369 }
365370 return false;
@@ -385,7 +390,7 @@ static int shell_output_kvs (struct shell_output *out)
385390 out -> stdout_bytes : out -> stderr_bytes ;
386391 shell_warn ("%s: %zu of %zu bytes truncated" ,
387392 is_stdout ? "stdout" : "stderr" ,
388- total - OUTPUT_LIMIT_BYTES ,
393+ total - out -> kvs_limit_bytes ,
389394 total );
390395 }
391396 }
@@ -1135,6 +1140,53 @@ static int shell_lost (flux_plugin_t *p,
11351140 return 0 ;
11361141}
11371142
1143+ static int get_output_limit (struct shell_output * out )
1144+ {
1145+ json_t * val = NULL ;
1146+ uint64_t size ;
1147+
1148+ /* Set default to unlimited (0) for single-user instances,
1149+ * O/w use the default multiuser output limit:
1150+ */
1151+ if (out -> shell -> broker_owner == getuid ())
1152+ out -> kvs_limit_string = "0" ;
1153+ else
1154+ out -> kvs_limit_string = MULTIUSER_OUTPUT_LIMIT ;
1155+
1156+ if (flux_shell_getopt_unpack (out -> shell ,
1157+ "output" ,
1158+ "{s?o}" ,
1159+ "limit" , & val ) < 0 ) {
1160+ shell_log_error ("Unable to unpack shell output.limit" );
1161+ return -1 ;
1162+ }
1163+ if (val != NULL ) {
1164+ if (json_is_integer (val )) {
1165+ out -> kvs_limit_bytes = (size_t ) json_integer_value (val );
1166+ if (out -> kvs_limit_bytes > 0 ) {
1167+ /* Need a string representation of limit for errors
1168+ */
1169+ char * s = strdup (encode_size (out -> kvs_limit_bytes ));
1170+ if (s && flux_shell_aux_set (out -> shell , NULL , s , free ) < 0 )
1171+ free (s );
1172+ else
1173+ out -> kvs_limit_string = s ;
1174+ }
1175+ return 0 ;
1176+ }
1177+ if (!(out -> kvs_limit_string = json_string_value (val ))) {
1178+ shell_log_error ("Unable to convert output.limit to string" );
1179+ return -1 ;
1180+ }
1181+ }
1182+ if (parse_size (out -> kvs_limit_string , & size ) < 0 ) {
1183+ shell_log_errno ("Invalid KVS output.limit=%s" , out -> kvs_limit_string );
1184+ return -1 ;
1185+ }
1186+ out -> kvs_limit_bytes = (size_t ) size ;
1187+ return 0 ;
1188+ }
1189+
11381190struct shell_output * shell_output_create (flux_shell_t * shell )
11391191{
11401192 struct shell_output * out ;
@@ -1147,6 +1199,8 @@ struct shell_output *shell_output_create (flux_shell_t *shell)
11471199 out -> stdout_buffer_type = "line" ;
11481200 out -> stderr_buffer_type = "none" ;
11491201
1202+ if (get_output_limit (out ) < 0 )
1203+ goto error ;
11501204 if (shell_output_check_alternate_output (out ) < 0 )
11511205 goto error ;
11521206 if (shell_output_check_alternate_buffer_type (out ) < 0 )
0 commit comments