freebsd / kyua

Testing framework for infrastructure software
BSD 3-Clause "New" or "Revised" License
147 stars 42 forks source link

sigsegv on illumos #211

Open ghost opened 4 years ago

ghost commented 4 years ago

I'm trying to port some tests over to kyua on illumos, and have problem with kyua itself -- I'm compiling all the dependencies (except system libraries) statically into one big executable. The same process works on FreeBSD (same Makefile and sources) and nearly follows what FreeBSD does in base system, so that should not be an issue.

Now running ~/kyua/kyua test in sed tests subdirectory copied over from FreeBSD's /usr/tests/usr.bin/sed make kyua crash:

$ ~/kyua/kyua test
*** Fatal signal 11 received
*** Log file is /home/yuripv/.kyua/logs/kyua.20200721-043513.log
*** Please report this problem to kyua-discuss@googlegroups.com detailing what you were doing before the crash happened; if possible, include the log file mentioned above
zsh: segmentation fault (core dumped)  ~/kyua/kyua test
fffffc7fffdf63e0 libstdc++.so.6.0.24`std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string+1()
fffffc7fffdf6410 std::auto_ptr<utils::fs::directory_entry>::reset+0x32()
fffffc7fffdf6820 utils::fs::detail::directory_iterator::impl::next+0x2bd()
fffffc7fffdf6840 utils::fs::detail::directory_iterator::operator+++0x20()
fffffc7fffdf6c50 utils::fs::rm_r+0x2f4()
fffffc7fffdf6f90 utils::process::executor::exit_handle::impl::cleanup+0x183()
fffffc7fffdf7020 utils::process::executor::exit_handle::cleanup+0x74()

Apparently, it's: https://github.com/jmmv/kyua/blob/a685f911237e7badddbfb71f1301f640c71673d0/utils/fs/directory.cpp#L210

Adding debug prints before and after the line as following:

@@ -207,7 +208,9 @@ struct utils::fs::detail::directory_iterator::impl : utils::noncopyable {
             _entry.reset(NULL);
             close();
         } else {
+            LD(F("old=%s") % (void *)_entry.get());
             _entry.reset(new directory_entry(_dirent.d_name));
+            LD(F("new=%s") % (void *)_entry.get());
         }
     }
 };

...gives me the following in the log when run with --loglevel=debug:

...
20200721-042945 I 717229 src/kyua/utils/process/executor.cpp:368: Cleaning up exit_handle for exec_handle 717230
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:211: old=0
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:213: new=0xaa2d30
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:211: old=0xaa2d30
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:213: new=0xaa2d90
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:211: old=0xaa2d90
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:213: new=0xaa2cd0
20200721-042945 D 717229 src/kyua/utils/fs/operations.cpp:703: Descending into /tmp/kyua.CIqRXR/1/work
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:211: old=0
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:213: new=0xaa0360
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:211: old=0xaa0360
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:213: new=0xaa2eb0
20200721-042945 D 717229 src/kyua/utils/fs/operations.cpp:711: Removing empty directory /tmp/kyua.CIqRXR/1/work
20200721-042945 D 717229 src/kyua/utils/fs/directory.cpp:211: old=0x7478742e

I'm really lost as C++ is still uncharted territory for me, but last pointer seems to be stomped on.

The build is done using different gcc versions (7, 9, 10) all producing the same result.

Any hints on debugging this further?

ghost commented 4 years ago

Of course, this has nothing to do with c++, it's the difference in d_name member of struct dirent being char d_name[256] in linux and FreeBSD and char d_name[1] in illumos (Solaris), so we have memory corruption here reading into d_name not having the actual storage allocated.

I see #184 filed to make kyua use readdir() instead, can that be integrated?

For the moment I'll just use the following as (ugly) workaround:

diff --git a/utils/fs/directory.cpp b/utils/fs/directory.cpp
index ff7ad5e..a6fc9aa 100644
--- a/utils/fs/directory.cpp
+++ b/utils/fs/directory.cpp
@@ -32,6 +32,7 @@ extern "C" {
 #include <sys/types.h>

 #include <dirent.h>
+#include <limits.h>
 }

 #include <cerrno>
@@ -133,6 +134,10 @@ struct utils::fs::detail::directory_iterator::impl : utils::noncopyable {
     /// readdir_r(3) function.
     ::dirent _dirent;

+    /// Solaris and derivatives define d_name member of struct dirent
+    /// as char d_name[1], so we need to provide the actual storage.
+    char _d_name[NAME_MAX];
+
     /// Custom representation of the directory entry.
     ///
     /// This is separate from _dirent because this is the type we return to the