diff --git a/include/bu/process.h b/include/bu/process.h index 9c16f903cff..22e14eb03d2 100644 --- a/include/bu/process.h +++ b/include/bu/process.h @@ -159,6 +159,14 @@ BU_EXPORT extern void bu_process_exec(struct bu_process **info, const char *cmd, */ BU_EXPORT extern int bu_interactive(); + +/** + * @brief determine whether there is data pending on fd + * + * 1 if there is data, else 0 + */ +BU_EXPORT extern int bu_process_pending(int fd); + /** @} */ __END_DECLS diff --git a/src/libbu/process.c b/src/libbu/process.c index ac9bd0d9a8a..1d8372ec47f 100644 --- a/src/libbu/process.c +++ b/src/libbu/process.c @@ -1,7 +1,7 @@ /* P R O C E S S . C * BRL-CAD * - * Copyright (c) 2007-2022 United States Government as represented by + * Copyright (c) 2007-2023 United States Government as represented by * the U.S. Army Research Laboratory. * * This library is free software; you can redistribute it and/or @@ -543,6 +543,32 @@ bu_process_wait( # include #endif +int +bu_process_pending(int fd) +{ + int result; + +#if defined(_WIN32) + HANDLE out_fd = (HANDLE)_get_osfhandle(fd); + DWORD bytesAvailable = 0; + /* returns 1 on success, 0 on error */ + if (PeekNamedPipe(out_fd, NULL, 0, NULL, &bytesAvailable, NULL)) { + result = bytesAvailable; + } else { + result = -1; + } +#else + fd_set read_set; + FD_ZERO(&read_set); + FD_SET(fd, &read_set); + /* returns 1 on success, 0 on timeout, -1 on error */ + result = select(fd+1, &read_set, NULL, NULL, 0); +#endif + + /* collapse return to ignore amount to read or errors */ + return result > 0 ? 1 : 0; +} + int bu_interactive() { diff --git a/src/libged/nirt/nirt.c b/src/libged/nirt/nirt.c index 0ff0ad65591..ea52182dbd6 100644 --- a/src/libged/nirt/nirt.c +++ b/src/libged/nirt/nirt.c @@ -45,6 +45,8 @@ #include "bu/app.h" #include "bu/cmd.h" #include "bu/file.h" +#include "bu/snooze.h" +#include "bu/time.h" #include "bu/process.h" #include "vmath.h" @@ -83,6 +85,7 @@ ged_nirt_core(struct ged *gedp, int argc, const char *argv[]) char **gd_rt_cmd = NULL; int gd_rt_cmd_len = 0; int skip_drawn = 0; + int64_t start = 0; const char *nirt = NULL; char nirtcmd[MAXPATHLEN] = {0}; @@ -307,10 +310,20 @@ ged_nirt_core(struct ged *gedp, int argc, const char *argv[]) bu_vls_free(&p_vls); /* use to form "partition" part of nirt command above */ print: - while (bu_fgets(line, RT_MAXLINE, fp_err) != (char *)NULL) { - bu_vls_strcpy(&v, line); - bu_vls_trimspace(&v); - bu_vls_printf(gedp->ged_result_str, "%s\n", bu_vls_addr(&v)); + /* ensure nirt has started and has something to read from - with 5 second timeout */ + start = bu_gettime(); + while (!bu_process_pending(fileno(fp_err)) && !bu_process_pending(fileno(fp_out))) { + if ((bu_gettime() - start) > BU_SEC2USEC(5)) + break; + } + + /* check if nirt wrote anything to error on load */ + if (bu_process_pending(fileno(fp_err))) { + while (bu_fgets(line, RT_MAXLINE, fp_err) != (char *)NULL) { + bu_vls_strcpy(&v, line); + bu_vls_trimspace(&v); + bu_vls_printf(gedp->ged_result_str, "%s\n", bu_vls_addr(&v)); + } } if (DG_QRAY_TEXT(gedp->ged_gdp)) { @@ -397,6 +410,15 @@ ged_nirt_core(struct ged *gedp, int argc, const char *argv[]) bv_vlblock_free(vbp); } + /* check if nirt wrote any errors from shots */ + if (bu_process_pending(fileno(fp_err))) { + while (bu_fgets(line, RT_MAXLINE, fp_err) != (char *)NULL) { + bu_vls_strcpy(&v, line); + bu_vls_trimspace(&v); + bu_vls_printf(gedp->ged_result_str, "%s\n", bu_vls_addr(&v)); + } + } + bu_vls_free(&v); bu_process_close(p, BU_PROCESS_STDOUT);