[gjs: 1/2] system: Use RAII in System.dumpHeap and logging for file pointer
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 1/2] system: Use RAII in System.dumpHeap and logging for file pointer
- Date: Mon, 17 May 2021 05:07:18 +0000 (UTC)
commit 37ee770f9be8d664d11124098056bba8d5750410
Author: Philip Chimento <philip chimento gmail com>
Date: Tue Mar 16 21:29:51 2021 -0700
system: Use RAII in System.dumpHeap and logging for file pointer
Avoids accessing the file handle after it is destructed.
Avoids duplicating the js::DumpHeap() call and will be used later in
System.dumpMemoryInfo() as well, in GNOME/gjs#292.
Closes: #410
modules/system.cpp | 21 +++++++--------------
util/log.cpp | 19 ++++++++-----------
util/misc.h | 40 +++++++++++++++++++++++++++++++++++++++-
3 files changed, 54 insertions(+), 26 deletions(-)
---
diff --git a/modules/system.cpp b/modules/system.cpp
index f5e0340b..29eb7770 100644
--- a/modules/system.cpp
+++ b/modules/system.cpp
@@ -5,9 +5,6 @@
#include <config.h> // for GJS_VERSION
-#include <errno.h>
-#include <stdio.h> // for FILE, fclose, stdout
-#include <string.h> // for strerror
#include <time.h> // for tzset
#include <glib-object.h>
@@ -31,6 +28,7 @@
#include "gjs/jsapi-util.h"
#include "modules/system.h"
#include "util/log.h"
+#include "util/misc.h" // for LogFile
/* Note that this cannot be relied on to test whether two objects are the same!
* SpiderMonkey can move objects around in memory during garbage collection,
@@ -124,18 +122,13 @@ gjs_dump_heap(JSContext *cx,
if (!gjs_parse_call_args(cx, "dumpHeap", args, "|F", "filename", &filename))
return false;
- if (filename) {
- FILE *fp = fopen(filename, "a");
- if (!fp) {
- gjs_throw(cx, "Cannot dump heap to %s: %s", filename.get(),
- strerror(errno));
- return false;
- }
- js::DumpHeap(cx, fp, js::CollectNurseryBeforeDump);
- fclose(fp);
- } else {
- js::DumpHeap(cx, stdout, js::CollectNurseryBeforeDump);
+ LogFile file(filename);
+ if (file.has_error()) {
+ gjs_throw(cx, "Cannot dump heap to %s: %s", filename.get(),
+ file.errmsg());
+ return false;
}
+ js::DumpHeap(cx, file.fp(), js::CollectNurseryBeforeDump);
gjs_debug(GJS_DEBUG_CONTEXT, "Heap dumped to %s",
filename ? filename.get() : "stdout");
diff --git a/util/log.cpp b/util/log.cpp
index 93068a3b..3f5b52d4 100644
--- a/util/log.cpp
+++ b/util/log.cpp
@@ -3,6 +3,7 @@
// SPDX-FileCopyrightText: 2008 litl, LLC
#include <atomic> // for atomic_bool
+#include <memory> // for unique_ptr
#include <string> // for string
#include <type_traits> // for remove_reference<>::type
@@ -32,7 +33,7 @@
static std::atomic_bool s_initialized = ATOMIC_VAR_INIT(false);
static bool s_debug_log_enabled = false;
static bool s_print_thread = false;
-static FILE* s_logfp = nullptr;
+static std::unique_ptr<LogFile> s_log_file;
static GjsAutoPointer<GTimer, GTimer, g_timer_destroy> s_timer;
static std::vector<bool> s_enabled_topics;
@@ -131,16 +132,17 @@ void gjs_log_init() {
}
/* avoid truncating in case we're using shared logfile */
- s_logfp = fopen(log_file.c_str(), "a");
- if (!s_logfp)
+ s_log_file = std::make_unique<LogFile>(log_file.c_str());
+ if (s_log_file->has_error()) {
fprintf(stderr, "Failed to open log file `%s': %s\n",
log_file.c_str(), g_strerror(errno));
+ }
s_debug_log_enabled = true;
}
- if (!s_logfp)
- s_logfp = stderr;
+ if (!s_log_file)
+ s_log_file = std::make_unique<LogFile>(nullptr, stderr);
if (s_debug_log_enabled) {
auto* topics = g_getenv("GJS_DEBUG_TOPICS");
@@ -160,11 +162,6 @@ void gjs_log_cleanup() {
if (!s_initialized.compare_exchange_strong(expected, false))
return;
- if (s_logfp && s_logfp != stderr) {
- fclose(s_logfp);
- s_logfp = nullptr;
- }
-
s_timer = nullptr;
s_enabled_topics.clear();
}
@@ -231,7 +228,7 @@ gjs_debug(GjsDebugTopic topic,
s = s2;
}
- write_to_stream(s_logfp, topic_to_prefix(topic), s);
+ write_to_stream(s_log_file->fp(), topic_to_prefix(topic), s);
g_free(s);
}
diff --git a/util/misc.h b/util/misc.h
index b9b5b284..4c7cde3a 100644
--- a/util/misc.h
+++ b/util/misc.h
@@ -5,7 +5,8 @@
#ifndef UTIL_MISC_H_
#define UTIL_MISC_H_
-#include <stdlib.h> // for size_t
+#include <errno.h>
+#include <stdio.h> // for FILE, stdout
#include <string.h> // for memcpy
#include <glib.h> // for g_malloc
@@ -42,4 +43,41 @@ static inline void* _gjs_memdup2(const void* mem, size_t byte_size) {
return new_mem;
}
+/*
+ * LogFile:
+ * RAII class encapsulating access to a FILE* pointer that must be closed,
+ * unless it is an already-open fallback file such as stdout or stderr.
+ */
+class LogFile {
+ FILE* m_fp;
+ const char* m_errmsg;
+ bool m_should_close : 1;
+
+ LogFile(const LogFile&) = delete;
+ LogFile& operator=(const LogFile&) = delete;
+
+ public:
+ explicit LogFile(const char* filename, FILE* fallback_fp = stdout)
+ : m_errmsg(nullptr), m_should_close(false) {
+ if (filename) {
+ m_fp = fopen(filename, "a");
+ if (!m_fp)
+ m_errmsg = strerror(errno);
+ else
+ m_should_close = true;
+ } else {
+ m_fp = fallback_fp;
+ }
+ }
+
+ ~LogFile() {
+ if (m_should_close)
+ fclose(m_fp);
+ }
+
+ FILE* fp() { return m_fp; }
+ bool has_error() { return !!m_errmsg; }
+ const char* errmsg() { return m_errmsg; }
+};
+
#endif // UTIL_MISC_H_
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]