+2015-01-09 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/64206
+ * docs/internals/test-hello-world.exe.log.txt: Update, the log now
+ shows tempdir creation/cleanup.
+ * docs/_build/texinfo/libgccjit.texi: Regenerate.
+ * jit-logging.h (class gcc::jit::log_user): Add gcc::jit::tempdir
+ to the list of subclasses in the comment.
+ * jit-playback.c (gcc::jit::playback::context::context): Add a
+ comment clarifying when the tempdir gets cleaned up.
+ (gcc::jit::playback::context::compile): Pass the context's logger,
+ if any, to the tempdir.
+ (gcc::jit::playback::context::dlopen_built_dso): When creating the
+ gcc::jit::result, if GCC_JIT_BOOL_OPTION_DEBUGINFO is set, hand
+ over ownership of the tempdir to it.
+ * jit-result.c: Include "jit-tempdir.h".
+ (gcc::jit::result::result): Add tempdir param, saving it as
+ m_tempdir.
+ (gcc::jit::result::~result): Delete m_tempdir.
+ * jit-result.h (gcc::jit::result::result): Add tempdir param.
+ (gcc::jit::result::m_tempdir): New field.
+ * jit-tempdir.c (gcc::jit::tempdir::tempdir): Add logger param;
+ add JIT_LOG_SCOPE.
+ (gcc::jit::tempdir::create): Add JIT_LOG_SCOPE to log entry/exit,
+ and log m_path_template and m_path_tempdir.
+ (gcc::jit::tempdir::~tempdir): Add JIT_LOG_SCOPE to log
+ entry/exit, and log the unlink and rmdir calls.
+ * jit-tempdir.h: Include "jit-logging.h".
+ (class gcc::jit::tempdir): Make this be a subclass of log_user.
+ (gcc::jit::tempdir::tempdir): Add logger param.
+ * notes.txt: Update to show the two possible places where the
+ tempdir can be cleaned up.
+
2015-01-08 David Malcolm <dmalcolm@redhat.com>
* libgccjit.h (struct gcc_jit_context): Rewrite the descriptive
@copying
@quotation
-libgccjit 5.0.0 (experimental 20150108), January 08, 2015
+libgccjit 5.0.0 (experimental 20150109), January 09, 2015
David Malcolm
. . │ . .
. . │ playback::context dtor
. . ──> . .
- . . │ Cleanup tempdir .
+ . . │ Normally we cleanup the tempdir here:
. . │ ("fake.so" is unlinked from the
. . │ filesystem at this point)
+ . . │ If the client code requested debuginfo, the
+ . . │ cleanup happens later (in gcc_jit_result_release)
+ . . │ to make it easier on the debugger (see PR jit/64206)
. . <── . .
. . │ . .
. . │ end of recording::context::compile ()
──────────────────────────> . .
. . │ dlclose () the loaded DSO
. . │ (code becomes uncallable)
+ . . │ . .
+ . . │ If the client code requested debuginfo, then
+ . . │ cleanup of the tempdir was delayed.
+ . . │ If that was the case, clean it up now.
<─────────────────────────── . .
│ . . . .
JIT: entering: gcc::jit::playback::context::context(gcc::jit::recording::context*)
JIT: exiting: gcc::jit::playback::context::context(gcc::jit::recording::context*)
JIT: entering: gcc::jit::result* gcc::jit::playback::context::compile()
+JIT: entering: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int)
+JIT: exiting: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int)
+JIT: entering: bool gcc::jit::tempdir::create()
+JIT: m_path_template: /tmp/libgccjit-XXXXXX
+JIT: m_path_tempdir: /tmp/libgccjit-CKq1M9
+JIT: exiting: bool gcc::jit::tempdir::create()
JIT: entering: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*)
JIT: exiting: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*)
JIT: entering: void gcc::jit::playback::context::acquire_mutex()
JIT: argv[6]: (null)
JIT: exiting: void gcc::jit::playback::context::convert_to_dso(const char*)
JIT: entering: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
-JIT: entering: gcc::jit::result::result(gcc::jit::logger*, void*)
-JIT: exiting: gcc::jit::result::result(gcc::jit::logger*, void*)
+JIT: GCC_JIT_BOOL_OPTION_DEBUGINFO was set: handing over tempdir to jit::result
+JIT: entering: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*)
+JIT: exiting: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*)
JIT: exiting: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
JIT: entering: void gcc::jit::playback::context::release_mutex()
JIT: exiting: void gcc::jit::playback::context::release_mutex()
JIT: entering: gcc_jit_result_release
JIT: deleting result: 0x12f75d0
JIT: entering: virtual gcc::jit::result::~result()
+JIT: entering: gcc::jit::tempdir::~tempdir()
+JIT: unlinking .s file: /tmp/libgccjit-CKq1M9/fake.s
+JIT: unlinking .so file: /tmp/libgccjit-CKq1M9/fake.so
+JIT: removing tempdir: /tmp/libgccjit-CKq1M9
+JIT: exiting: gcc::jit::tempdir::~tempdir()
JIT: exiting: virtual gcc::jit::result::~result()
JIT: exiting: gcc_jit_result_release
JIT: gcc::jit::logger::~logger()
JIT: entering: gcc::jit::playback::context::context(gcc::jit::recording::context*)
JIT: exiting: gcc::jit::playback::context::context(gcc::jit::recording::context*)
JIT: entering: gcc::jit::result* gcc::jit::playback::context::compile()
+JIT: entering: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int)
+JIT: exiting: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int)
+JIT: entering: bool gcc::jit::tempdir::create()
+JIT: m_path_template: /tmp/libgccjit-XXXXXX
+JIT: m_path_tempdir: /tmp/libgccjit-CKq1M9
+JIT: exiting: bool gcc::jit::tempdir::create()
JIT: entering: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*)
JIT: exiting: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*)
JIT: entering: void gcc::jit::playback::context::acquire_mutex()
JIT: argv[6]: (null)
JIT: exiting: void gcc::jit::playback::context::convert_to_dso(const char*)
JIT: entering: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
-JIT: entering: gcc::jit::result::result(gcc::jit::logger*, void*)
-JIT: exiting: gcc::jit::result::result(gcc::jit::logger*, void*)
+JIT: GCC_JIT_BOOL_OPTION_DEBUGINFO was set: handing over tempdir to jit::result
+JIT: entering: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*)
+JIT: exiting: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*)
JIT: exiting: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
JIT: entering: void gcc::jit::playback::context::release_mutex()
JIT: exiting: void gcc::jit::playback::context::release_mutex()
JIT: entering: gcc_jit_result_release
JIT: deleting result: 0x12f75d0
JIT: entering: virtual gcc::jit::result::~result()
+JIT: entering: gcc::jit::tempdir::~tempdir()
+JIT: unlinking .s file: /tmp/libgccjit-CKq1M9/fake.s
+JIT: unlinking .so file: /tmp/libgccjit-CKq1M9/fake.so
+JIT: removing tempdir: /tmp/libgccjit-CKq1M9
+JIT: exiting: gcc::jit::tempdir::~tempdir()
JIT: exiting: virtual gcc::jit::result::~result()
JIT: exiting: gcc_jit_result_release
JIT: gcc::jit::logger::~logger()
- class gcc::jit::playback::context
+ - class gcc::jit::tempdir
+
- class gcc::jit::result
The log_user class keeps the reference-count of a logger up-to-date. */
playback::context::~context ()
{
JIT_LOG_SCOPE (get_logger ());
- if (m_tempdir)
- delete m_tempdir;
+
+ /* Normally the playback::context is responsible for cleaning up the
+ tempdir (including "fake.so" within the filesystem).
+
+ In the normal case, clean it up now.
+
+ However m_tempdir can be NULL if the context has handed over
+ responsibility for the tempdir cleanup to the jit::result object, so
+ that the cleanup can be delayed (see PR jit/64206). If that's the
+ case this "delete NULL;" is a no-op. */
+ delete m_tempdir;
+
m_functions.release ();
}
int keep_intermediates =
get_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES);
- m_tempdir = new tempdir (keep_intermediates);
+ m_tempdir = new tempdir (get_logger (), keep_intermediates);
if (!m_tempdir->create ())
return NULL;
add_error (NULL, "%s", error);
}
if (handle)
- result_obj = new result (get_logger (), handle);
+ {
+ /* We've successfully dlopened the result; create a
+ jit::result object to wrap it.
+
+ We're done with the tempdir for now, but if the user
+ has requested debugging, the user's debugger might not
+ be capable of dealing with the .so file being unlinked
+ immediately, so keep it around until after the result
+ is released. We do this by handing over ownership of
+ the jit::tempdir to the result. See PR jit/64206. */
+ tempdir *handover_tempdir;
+ if (get_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO))
+ {
+ handover_tempdir = m_tempdir;
+ m_tempdir = NULL;
+ /* The tempdir will eventually be cleaned up in the
+ jit::result's dtor. */
+ log ("GCC_JIT_BOOL_OPTION_DEBUGINFO was set:"
+ " handing over tempdir to jit::result");
+ }
+ else
+ {
+ handover_tempdir = NULL;
+ /* ... and retain ownership of m_tempdir so we clean it
+ up it the playback::context's dtor. */
+ log ("GCC_JIT_BOOL_OPTION_DEBUGINFO was not set:"
+ " retaining ownership of tempdir");
+ }
+
+ result_obj = new result (get_logger (), handle, handover_tempdir);
+ }
else
result_obj = NULL;
#include "jit-common.h"
#include "jit-logging.h"
#include "jit-result.h"
+#include "jit-tempdir.h"
namespace gcc {
namespace jit {
/* Constructor for gcc::jit::result. */
result::
-result(logger *logger, void *dso_handle) :
+result(logger *logger, void *dso_handle, tempdir *tempdir_) :
log_user (logger),
- m_dso_handle (dso_handle)
+ m_dso_handle (dso_handle),
+ m_tempdir (tempdir_)
{
JIT_LOG_SCOPE (get_logger ());
}
JIT_LOG_SCOPE (get_logger ());
dlclose (m_dso_handle);
+
+ /* Responsibility for cleaning up the tempdir (including "fake.so" within
+ the filesystem) might have been handed to us by the playback::context,
+ so that the cleanup can be delayed (see PR jit/64206).
+
+ If so, clean it up now. */
+ delete m_tempdir;
}
/* Attempt to locate the given function by name within the
class result : public log_user
{
public:
- result(logger *logger, void *dso_handle);
+ result(logger *logger, void *dso_handle, tempdir *tempdir_);
virtual ~result();
private:
void *m_dso_handle;
+ tempdir *m_tempdir;
};
} // namespace gcc::jit
/* The constructor for the jit::tempdir object.
The real work is done by the jit::tempdir::create method. */
-gcc::jit::tempdir::tempdir (int keep_intermediates)
- : m_keep_intermediates (keep_intermediates),
+gcc::jit::tempdir::tempdir (logger *logger, int keep_intermediates)
+ : log_user (logger),
+ m_keep_intermediates (keep_intermediates),
m_path_template (NULL),
m_path_tempdir (NULL),
m_path_c_file (NULL),
m_path_s_file (NULL),
m_path_so_file (NULL)
{
+ JIT_LOG_SCOPE (get_logger ());
}
/* Do the real work of creating the on-disk tempdir.
bool
gcc::jit::tempdir::create ()
{
+ JIT_LOG_SCOPE (get_logger ());
+
m_path_template = make_tempdir_path_template ();
if (!m_path_template)
return false;
+ log ("m_path_template: %s", m_path_template);
+
/* Create tempdir using mkdtemp. This is created with 0700 perms and
is unique. Hence no other (non-root) users should have access to
the paths within it. */
m_path_tempdir = mkdtemp (m_path_template);
if (!m_path_tempdir)
return false;
+ log ("m_path_tempdir: %s", m_path_tempdir);
+
m_path_c_file = concat (m_path_tempdir, "/fake.c", NULL);
m_path_s_file = concat (m_path_tempdir, "/fake.s", NULL);
m_path_so_file = concat (m_path_tempdir, "/fake.so", NULL);
gcc::jit::tempdir::~tempdir ()
{
+ JIT_LOG_SCOPE (get_logger ());
+
if (m_keep_intermediates)
fprintf (stderr, "intermediate files written to %s\n", m_path_tempdir);
else
{
/* Clean up .s/.so and tempdir. */
if (m_path_s_file)
- unlink (m_path_s_file);
+ {
+ log ("unlinking .s file: %s", m_path_s_file);
+ unlink (m_path_s_file);
+ }
if (m_path_so_file)
- unlink (m_path_so_file);
+ {
+ log ("unlinking .so file: %s", m_path_so_file);
+ unlink (m_path_so_file);
+ }
if (m_path_tempdir)
- rmdir (m_path_tempdir);
+ {
+ log ("removing tempdir: %s", m_path_tempdir);
+ rmdir (m_path_tempdir);
+ }
}
free (m_path_template);
#ifndef JIT_TEMPDIR_H
#define JIT_TEMPDIR_H
+#include "jit-logging.h"
+
namespace gcc {
namespace jit {
It is normally deleted from the filesystem in the playback::context's
dtor, unless GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES was set. */
-class tempdir
+class tempdir : public log_user
{
public:
- tempdir (int keep_intermediates);
+ tempdir (logger *logger, int keep_intermediates);
~tempdir ();
bool create ();
. . │ . .
. . │ playback::context dtor
. . ──> . .
- . . │ Cleanup tempdir .
+ . . │ Normally we cleanup the tempdir here:
. . │ ("fake.so" is unlinked from the
. . │ filesystem at this point)
+ . . │ If the client code requested debuginfo, the
+ . . │ cleanup happens later (in gcc_jit_result_release)
+ . . │ to make it easier on the debugger (see PR jit/64206)
. . <── . .
. . │ . .
. . │ end of recording::context::compile ()
──────────────────────────> . .
. . │ dlclose () the loaded DSO
. . │ (code becomes uncallable)
+ . . │ . .
+ . . │ If the client code requested debuginfo, then
+ . . │ cleanup of the tempdir was delayed.
+ . . │ If that was the case, clean it up now.
<─────────────────────────── . .
│ . . . .