@@ -1576,6 +1576,7 @@ struct attach_ctx {
15761576 flux_watcher_t * sigtstp_w ;
15771577 flux_watcher_t * notify_timer ;
15781578 struct flux_pty_client * pty_client ;
1579+ int pty_capture ;
15791580 struct timespec t_sigint ;
15801581 flux_watcher_t * stdin_w ;
15811582 zlist_t * stdin_rpcs ;
@@ -1646,6 +1647,15 @@ static void handle_output_data (struct attach_ctx *ctx, json_t *context)
16461647 log_msg_exit ("stream data read before header" );
16471648 if (iodecode (context , & stream , & rank , & data , & len , NULL ) < 0 )
16481649 log_msg_exit ("malformed event context" );
1650+ /*
1651+ * If this process is attached to a pty (ctx->pty_client != NULL)
1652+ * and output corresponds to rank 0 and the interactive pty is being
1653+ * captured, then this data is a duplicate, so do nothing.
1654+ */
1655+ if (ctx -> pty_client != NULL
1656+ && streq (rank , "0" )
1657+ && ctx -> pty_capture )
1658+ goto out ;
16491659 if (streq (stream , "stdout" ))
16501660 fp = stdout ;
16511661 else
@@ -1654,8 +1664,14 @@ static void handle_output_data (struct attach_ctx *ctx, json_t *context)
16541664 if (optparse_hasopt (ctx -> p , "label-io" ))
16551665 fprintf (fp , "%s: " , rank );
16561666 fwrite (data , len , 1 , fp );
1667+ /* If attached to a pty, terminal is in raw mode so a carriage
1668+ * return will be necessary to return cursor to the start of line.
1669+ */
1670+ if (ctx -> pty_client )
1671+ fputc ('\r' , fp );
16571672 fflush (fp );
16581673 }
1674+ out :
16591675 free (data );
16601676}
16611677
@@ -1725,6 +1741,11 @@ static void handle_output_log (struct attach_ctx *ctx,
17251741 fprintf (stderr , ":%d" , line );
17261742 }
17271743 fprintf (stderr , ": %s\n" , msg );
1744+ /* If attached to a pty, terminal is in raw mode so a carriage
1745+ * return will be necessary to return cursor to the start of line.
1746+ */
1747+ if (ctx -> pty_client )
1748+ fprintf (stderr , "\r" );
17281749 }
17291750}
17301751
@@ -2314,13 +2335,15 @@ void attach_exec_event_continuation (flux_future_t *f, void *arg)
23142335 if (streq (name , "shell.init" )) {
23152336 const char * pty_service = NULL ;
23162337 if (json_unpack (context ,
2317- "{s:i s:s s?s}" ,
2338+ "{s:i s:s s?s s?i }" ,
23182339 "leader-rank" ,
23192340 & ctx -> leader_rank ,
23202341 "service" ,
23212342 & service ,
23222343 "pty" ,
2323- & pty_service ) < 0 )
2344+ & pty_service ,
2345+ "capture" ,
2346+ & ctx -> pty_capture ) < 0 )
23242347 log_err_exit ("error decoding shell.init context" );
23252348 if (!(ctx -> service = strdup (service )))
23262349 log_err_exit ("strdup service from shell.init" );
@@ -2333,15 +2356,14 @@ void attach_exec_event_continuation (flux_future_t *f, void *arg)
23332356 * to process normal stdio. (This may be because the job is
23342357 * already complete).
23352358 */
2359+ attach_output_start (ctx );
23362360 if (pty_service ) {
23372361 if (ctx -> readonly )
23382362 log_msg_exit ("Cannot connect to pty in readonly mode" );
23392363 attach_pty (ctx , pty_service );
23402364 }
2341- else {
2365+ else
23422366 attach_setup_stdin (ctx );
2343- attach_output_start (ctx );
2344- }
23452367 } else if (streq (name , "shell.start" )) {
23462368 if (MPIR_being_debugged )
23472369 setup_mpir_interface (ctx , context );
0 commit comments