From d9ae96c2598f7f21ab613bfcd6bcd4a6900d5cb6 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Mon, 13 Sep 2004 20:19:01 +0000 Subject: [PATCH] Update output streams and associated docs. IMPORTANT NOTE: when sendout ompi_output() strings to files, note that the file goes into the session directory. If the session directory does not exist yet when you call ompi_output() and you are sending the string to a file, THE STRING WILL BE DROPPED (in terms of the file -- it will still be sent to all other locations that were specified). This should really only be a factor for a fairly small portion of things during initialization of a process -- basically, until the session directory exists, nothing will be written to a file. ompi_output() will automatically take care of creating the file and writing to it once the session directory has been created. So it is valid to: id = ompi_output(...something with file set...) ompi_output(id, "blah!"); /* ... process session directory is created ... */ ompi_output(id, "wazzlebort!"); In this case, the output file will be: ----- [WARNING: 1 lines lost because the Open MPI process session directory did not exist when ompi_output() was invoked] wazzlebort! ----- This commit was SVN r2637. --- src/util/output.c | 135 ++++++++++++++++++++++++++++++---------------- src/util/output.h | 31 +++++++++-- 2 files changed, 117 insertions(+), 49 deletions(-) diff --git a/src/util/output.c b/src/util/output.c index 4c02e0b91c..20b2b43bff 100644 --- a/src/util/output.c +++ b/src/util/output.c @@ -15,9 +15,11 @@ #include #include #include +#include #include "include/constants.h" #include "util/output.h" +#include "util/proc_info.h" #include "threads/mutex.h" @@ -45,6 +47,7 @@ static ompi_output_stream_t verbose = { * Private functions */ static int do_open(int output_id, ompi_output_stream_t *lds); +static int open_file(int i); static void free_descriptor(int output_id); static void output(int output_id, char *format, va_list arglist); @@ -68,8 +71,11 @@ struct output_desc_t { bool ldi_stdout; bool ldi_stderr; - int ldi_fd; + bool ldi_file; + bool ldi_file_want_append; char *ldi_file_suffix; + int ldi_fd; + int ldi_file_num_lines_lost; }; typedef struct output_desc_t output_desc_t; @@ -97,7 +103,11 @@ bool ompi_output_init(void) info[i].ldi_enabled = false; info[i].ldi_syslog = false; + info[i].ldi_file = false; + info[i].ldi_file_suffix = NULL; + info[i].ldi_file_want_append = false; info[i].ldi_fd = -1; + info[i].ldi_file_num_lines_lost = 0; } /* Initialize the mutex that protects the output */ @@ -179,7 +189,7 @@ void ompi_output_reopen_all(void) lds.lds_prefix = info[i].ldi_prefix; lds.lds_want_stdout = info[i].ldi_stdout; lds.lds_want_stderr = info[i].ldi_stderr; - lds.lds_want_file = (-1 == info[i].ldi_fd) ? false: true; + lds.lds_want_file = (-1 == info[i].ldi_fd) ? false : true; /* open all streams in append mode */ lds.lds_want_file_append = true; lds.lds_file_suffix = info[i].ldi_file_suffix; @@ -303,10 +313,8 @@ void ompi_output_finalize(void) * (especially upon reopen). */ static int do_open(int output_id, ompi_output_stream_t *lds) - { - int i; - int flags; - char *filename; +{ + int i, ret; /* Setup */ @@ -379,50 +387,70 @@ static int do_open(int output_id, ompi_output_stream_t *lds) info[i].ldi_stderr = lds->lds_want_stderr; info[i].ldi_fd = -1; + info[i].ldi_file = lds->lds_want_file; + info[i].ldi_file_suffix = (NULL == lds->lds_file_suffix) ? NULL : + strdup(lds->lds_file_suffix); + info[i].ldi_file_want_append = lds->lds_want_file_append; + info[i].ldi_file_num_lines_lost = 0; if (lds->lds_want_file) { - - /* Setup the filename and open flags */ - -#if 0 - filename = ompi_get_tmpdir(); -#else - ompi_output(0, "WARNING: need to implement session dir (%s, %d)\n", - __FILE__, __LINE__); - filename = malloc(256); - strcpy(filename, "/tmp"); -#endif - strcat(filename, "/ompi-"); - if (lds->lds_file_suffix != NULL) { - info[i].ldi_file_suffix = strdup(lds->lds_file_suffix); - strcat(filename, lds->lds_file_suffix); - } else { - info[i].ldi_file_suffix = NULL; - strcat(filename, "output.txt"); + if (OMPI_SUCCESS != (ret = open_file(i))) { + return ret; } - flags = O_CREAT | O_RDWR; - if (!lds->lds_want_file_append) { - flags |= O_TRUNC; - } - - /* Actually open the file */ - - info[i].ldi_fd = open(filename, flags, 0644); - if (-1 == info[i].ldi_fd) { - info[i].ldi_used = false; - return OMPI_ERR_IN_ERRNO; - } - - /* Make the file be close-on-exec to prevent child inheritance - problems */ - - fcntl(info[i].ldi_fd, F_SETFD, 1); - free(filename); } return i; } +static int open_file(int i) +{ + int flags; + char *dir, *filename; + + /* Setup the filename and open flags */ + + dir = ompi_process_info.proc_session_dir; + if (NULL != dir) { + filename = malloc(MAXPATHLEN); + if (NULL == filename) { + return OMPI_ERR_OUT_OF_RESOURCE; + } + strcpy(filename, dir); + strcat(filename, "/output-"); + if (info[i].ldi_file_suffix != NULL) { + strcat(filename, info[i].ldi_file_suffix); + } else { + info[i].ldi_file_suffix = NULL; + strcat(filename, "output.txt"); + } + flags = O_CREAT | O_RDWR; + if (!info[i].ldi_file_want_append) { + flags |= O_TRUNC; + } + + /* Actually open the file */ + + info[i].ldi_fd = open(filename, flags, 0644); + printf("output: opening file: %s\n", filename); + if (-1 == info[i].ldi_fd) { + info[i].ldi_used = false; + return OMPI_ERR_IN_ERRNO; + } + + /* Make the file be close-on-exec to prevent child inheritance + problems */ + + fcntl(info[i].ldi_fd, F_SETFD, 1); + free(filename); + } + + /* Return successfully even if the session dir did not exist yet; + we'll try opening it later */ + + return OMPI_SUCCESS; +} + + /* * Free all the resources associated with a descriptor. */ @@ -538,10 +566,27 @@ static void output(int output_id, char *format, va_list arglist) fflush(stderr); } - /* File output */ + /* File output -- first check to see if the file opening was + delayed. If so, try to open it. If we failed to open it, then + just discard (there are big warnings in the ompi_output.h docs + about this!). */ - if (ldi->ldi_fd != -1) { - write(ldi->ldi_fd, temp_str, total_len); + if (ldi->ldi_file) { + if (ldi->ldi_fd == -1) { + if (OMPI_SUCCESS != open_file(output_id)) { + ++ldi->ldi_file_num_lines_lost; + } else if (ldi->ldi_file_num_lines_lost > 0) { + char buffer[BUFSIZ]; + memset(buffer, 0, BUFSIZ); + snprintf(buffer, BUFSIZ - 1, "[WARNING: %d lines lost because the Open MPI process session directory did\n not exist when ompi_output() was invoked]\n", ldi->ldi_file_num_lines_lost); + write(ldi->ldi_fd, buffer, strlen(buffer)); + ldi->ldi_file_num_lines_lost = 0; + } + } + if (ldi->ldi_fd != -1) { + printf("proc session dir: %s\n", ompi_process_info.proc_session_dir); + write(ldi->ldi_fd, temp_str, total_len); + } } OMPI_THREAD_UNLOCK(&mutex); diff --git a/src/util/output.h b/src/util/output.h index fd464b9fe5..bee6b9d426 100644 --- a/src/util/output.h +++ b/src/util/output.h @@ -22,6 +22,14 @@ * * Which outputs to use are specified during ompi_output_open(). * + * WARNING: When using "file" as an output destination, be aware that + * the file may not exist until the session directory for the process + * exists. This is at least part of the way through MPI_INIT (for + * example). Most MCA components and internals of Open MPI won't be + * affected by this, but some RTE / startup aspects of Open MPI will + * not be able to write to a file for output. See ompi_output() for + * details on what happens in these cases. + * * ompi_output_open() returns an integer handle that is used in * successive calls to OMPI_OUTPUT() and ompi_output() to send output to * the stream. @@ -170,10 +178,14 @@ struct ompi_output_stream_t { * indicates the string suffix to add to the filename. * * The output file will be in the OMPI session directory and have a - * OMPI-generated prefix (generally "$sessiondir/ompi-"). The suffix - * is intended to give stream users a chance to write their output - * into unique files. If this field is NULL, the suffix - * "output.txt" is used. + * OMPI-generated prefix (generally "$proc_sessiondir/output-"). + * The suffix is intended to give stream users a chance to write + * their output into unique files. If this field is NULL, the + * suffix "output.txt" is used. + * + * Note that it is possible that the process session directory does + * not exist when ompi_output_open() is invoked. See ompi_output() + * for details on what happens in this situation. */ char *lds_file_suffix; }; @@ -226,6 +238,10 @@ extern "C" { * It is safe to have multiple threads invoke this function * simultaneously; their execution will be serialized in an * unspecified manner. + * + * Be sure to see ompi_output() for a description of what happens + * when open_open() / ompi_output() is directed to send output to a + * file but the process session directory does not yet exist. */ int ompi_output_open(ompi_output_stream_t *lds); @@ -302,6 +318,13 @@ extern "C" { * this function will append newlines as necessary. * * Verbosity levels are ignored in this function. + * + * Note that for output streams that are directed to files, the + * files are stored under the process' session directory. If the + * session directory does not exist when ompi_output() is invoked, + * the output will be discarded! Once the session directory is + * created, ompi_output() will automatically create the file and + * writing to it. */ void ompi_output(int output_id, char *format, ...);