diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 64431a60aef3..ece7aa06006a 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -4028,4 +4028,63 @@ int __kmp_execute_tasks_oncore(kmp_info_t *thread, kmp_int32 gtid, #endif /* USE_ITT_BUILD */ kmp_int32 is_constrained); +/// This class safely opens and closes a C-style FILE* object using RAII +/// semantics. There are also methods which allow using stdout or stderr as +/// the underlying FILE* object. With the implicit conversion operator to +/// FILE*, an object with this type can be used in any function which takes +/// a FILE* object e.g., fprintf(). +/// No close method is needed at use sites. +class kmp_safe_raii_file_t { + FILE *f; + + void close() { + if (f && f != stdout && f != stderr) { + fclose(f); + f = nullptr; + } + } + +public: + kmp_safe_raii_file_t() : f(nullptr) {} + kmp_safe_raii_file_t(const char *filename, const char *mode, + const char *env_var = nullptr) + : f(nullptr) { + open(filename, mode, env_var); + } + ~kmp_safe_raii_file_t() { close(); } + + /// Open filename using mode. This is automatically closed in the destructor. + /// The env_var parameter indicates the environment variable the filename + /// came from if != nullptr. + void open(const char *filename, const char *mode, + const char *env_var = nullptr) { + KMP_ASSERT(!f); + f = fopen(filename, mode); + if (!f) { + int code = errno; + if (env_var) { + __kmp_fatal(KMP_MSG(CantOpenFileForReading, filename), KMP_ERR(code), + KMP_HNT(CheckEnvVar, env_var, filename), __kmp_msg_null); + } else { + __kmp_fatal(KMP_MSG(CantOpenFileForReading, filename), KMP_ERR(code), + __kmp_msg_null); + } + } + } + /// Set the FILE* object to stdout and output there + /// No open call should happen before this call. + void set_stdout() { + KMP_ASSERT(!f); + f = stdout; + } + /// Set the FILE* object to stderr and output there + /// No open call should happen before this call. + void set_stderr() { + KMP_ASSERT(!f); + f = stderr; + } + operator bool() { return bool(f); } + operator FILE *() { return f; } +}; + #endif /* KMP_H */ diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index 8f77f36ed5be..e232e301e366 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -4210,17 +4210,10 @@ static void __kmp_aux_affinity_initialize(void) { } } - FILE *f = fopen("/proc/cpuinfo", "r"); - if (f == NULL) { - msg_id = kmp_i18n_str_CantOpenCpuinfo; - } else { - file_name = "/proc/cpuinfo"; - depth = - __kmp_affinity_create_cpuinfo_map(&address2os, &line, &msg_id, f); - fclose(f); - if (depth == 0) { - KMP_EXIT_AFF_NONE; - } + kmp_safe_raii_file_t f("/proc/cpuinfo", "r"); + depth = __kmp_affinity_create_cpuinfo_map(&address2os, &line, &msg_id, f); + if (depth == 0) { + KMP_EXIT_AFF_NONE; } } @@ -4313,8 +4306,10 @@ static void __kmp_aux_affinity_initialize(void) { else if (__kmp_affinity_top_method == affinity_top_method_cpuinfo) { const char *filename; + const char *env_var = nullptr; if (__kmp_cpuinfo_file != NULL) { filename = __kmp_cpuinfo_file; + env_var = "KMP_CPUINFO_FILE"; } else { filename = "/proc/cpuinfo"; } @@ -4323,20 +4318,9 @@ static void __kmp_aux_affinity_initialize(void) { KMP_INFORM(AffParseFilename, "KMP_AFFINITY", filename); } - FILE *f = fopen(filename, "r"); - if (f == NULL) { - int code = errno; - if (__kmp_cpuinfo_file != NULL) { - __kmp_fatal(KMP_MSG(CantOpenFileForReading, filename), KMP_ERR(code), - KMP_HNT(NameComesFrom_CPUINFO_FILE), __kmp_msg_null); - } else { - __kmp_fatal(KMP_MSG(CantOpenFileForReading, filename), KMP_ERR(code), - __kmp_msg_null); - } - } + kmp_safe_raii_file_t f(filename, "r", env_var); int line = 0; depth = __kmp_affinity_create_cpuinfo_map(&address2os, &line, &msg_id, f); - fclose(f); if (depth < 0) { KMP_ASSERT(msg_id != kmp_i18n_null); if (line > 0) { diff --git a/openmp/runtime/src/kmp_lock.cpp b/openmp/runtime/src/kmp_lock.cpp index 38b43a36fcb8..5447471e718d 100644 --- a/openmp/runtime/src/kmp_lock.cpp +++ b/openmp/runtime/src/kmp_lock.cpp @@ -1891,20 +1891,6 @@ static float percent(kmp_uint32 count, kmp_uint32 total) { return (total == 0) ? 0.0 : (100.0 * count) / total; } -static FILE *__kmp_open_stats_file() { - if (strcmp(__kmp_speculative_statsfile, "-") == 0) - return stdout; - - size_t buffLen = KMP_STRLEN(__kmp_speculative_statsfile) + 20; - char buffer[buffLen]; - KMP_SNPRINTF(&buffer[0], buffLen, __kmp_speculative_statsfile, - (kmp_int32)getpid()); - FILE *result = fopen(&buffer[0], "w"); - - // Maybe we should issue a warning here... - return result ? result : stdout; -} - void __kmp_print_speculative_stats() { kmp_adaptive_lock_statistics_t total = destroyedStats; kmp_adaptive_lock_info_t *lck; @@ -1921,7 +1907,16 @@ void __kmp_print_speculative_stats() { if (totalSections <= 0) return; - FILE *statsFile = __kmp_open_stats_file(); + kmp_safe_raii_file_t statsFile; + if (strcmp(__kmp_speculative_statsfile, "-") == 0) { + statsFile.set_stdout(); + } else { + size_t buffLen = KMP_STRLEN(__kmp_speculative_statsfile) + 20; + char buffer[buffLen]; + KMP_SNPRINTF(&buffer[0], buffLen, __kmp_speculative_statsfile, + (kmp_int32)getpid()); + statsFile.open(buffer, "w"); + } fprintf(statsFile, "Speculative lock statistics (all approximate!)\n"); fprintf(statsFile, " Lock parameters: \n" @@ -1953,9 +1948,6 @@ void __kmp_print_speculative_stats() { fprintf(statsFile, " Hard failures : %10d (%5.1f%%)\n", t->hardFailedSpeculations, percent(t->hardFailedSpeculations, totalSpeculations)); - - if (statsFile != stdout) - fclose(statsFile); } #define KMP_INC_STAT(lck, stat) (lck->lk.adaptive.stats.stat++) diff --git a/openmp/runtime/src/kmp_stats.cpp b/openmp/runtime/src/kmp_stats.cpp index 55ac18a4312c..cc881b76398d 100644 --- a/openmp/runtime/src/kmp_stats.cpp +++ b/openmp/runtime/src/kmp_stats.cpp @@ -692,8 +692,7 @@ void kmp_stats_output_module::windupExplicitTimers() { void kmp_stats_output_module::printPloticusFile() { int i; int size = __kmp_stats_list->size(); - FILE *plotOut = fopen(plotFileName, "w+"); - + kmp_safe_raii_file_t plotOut(plotFileName, "w+"); fprintf(plotOut, "#proc page\n" " pagesize: 15 10\n" " scale: 1.0\n\n"); @@ -746,7 +745,6 @@ void kmp_stats_output_module::printPloticusFile() { fprintf(plotOut, "#proc legend\n" " format: down\n" " location: max max\n\n"); - fclose(plotOut); return; } @@ -797,14 +795,16 @@ void kmp_stats_output_module::outputStats(const char *heading) { normal timer stats */ statistic allCounters[COUNTER_LAST]; - FILE *statsOut = - !outputFileName.empty() ? fopen(outputFileName.c_str(), "a+") : stderr; - if (!statsOut) - statsOut = stderr; + kmp_safe_raii_file_t statsOut; + if (!outputFileName.empty()) { + statsOut.open(outputFileName.c_str(), "a+"); + } else { + statsOut.set_stderr(); + } - FILE *eventsOut; + kmp_safe_raii_file_t eventsOut; if (eventPrintingEnabled()) { - eventsOut = fopen(eventsFileName, "w+"); + eventsOut.open(eventsFileName, "w+"); } printHeaderInfo(statsOut); @@ -855,16 +855,12 @@ void kmp_stats_output_module::outputStats(const char *heading) { if (eventPrintingEnabled()) { printPloticusFile(); - fclose(eventsOut); } fprintf(statsOut, "Aggregate for all threads\n"); printTimerStats(statsOut, &allStats[0], &totalStats[0]); fprintf(statsOut, "\n"); printCounterStats(statsOut, &allCounters[0]); - - if (statsOut != stderr) - fclose(statsOut); } /* ************* exported C functions ************** */