nnn: "illegal hardware instruction" on macOS compiled nnn when invoking any plugin

Environment details (Put x in the checkbox along with the information)

[x] Operating System: macOS Catalina 10.15.7 [ ] Desktop Environment: [x] Terminal Emulator: iTerm2 (also occurs on Terminal) [x] Shell: zsh 5.7.1 (also occurs on bash 5.0.18) [ ] Custom desktop opener (if applicable): [ ] Program options used: [x] Configuration options set: NNN_PLUG='i:ipinfo' NNN_FIFO='/tmp/nnn.fifo' [x] Issue exists on nnn master

Exact steps to reproduce the issue

  1. Compile nnn with or without flags.
  2. Install plugins to ~/.config/nnn/plugins
  3. Enable any plugin with NNN_PLUG.
  4. Start nnn
  5. Invoke any plugin
  6. nnn crashes, leaving the line: zsh: illegal hardware instruction ./nnn

This does not occur when installing nnn via homebrew. I initially discovered the issue when compiling with O_NERD=1 for the icons, but it occurs without any flags set as well.

Debug output:

$ cat /tmp/nnndbg
ln 7686: VERSION=3.5
ln 7714: home=/Users/p
ln 7445: cfgpath=/Users/p/.config
ln 7451: cfgpath=/Users/p/.config/nnn
ln 7477: selpath=/Users/p/.config/nnn/.selection
ln 7721: opener=/usr/bin/open
ln 7802: getenv(envs[ENV_VISUAL])=(null)
ln 7803: getenv(envs[ENV_EDITOR])=nvim
ln 7804: editor=nvim
ln 7808: pager=less
ln 7812: shell=/bin/zsh
ln 7814: getenv("PWD")=/Users/p/Code/nnn
ln 1712: COLORS=256
ln 1713: COLOR_PAIRS=32767
ln 4972: __FUNCTION__=dentfill
ln 5209: ts2.tv_nsec - ts1.tv_nsec=237000
ln 5712: __FUNCTION__=redraw
ln 5727: path=/Users/p/Code/nnn

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 51 (34 by maintainers)

Most upvoted comments

And running the tests.

No, thank you so much for reporting the issue!

The issue is fixed in master now, thank you!

For later reference, found a similar defect here.

The following patch should work for you:

iff --git a/src/nnn.c b/src/nnn.c
index 8328718..4b1bae5 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -1016,6 +1016,8 @@ static inline bool getutil(char *util)
 /*
  * Updates out with "dir/name or "/name"
  * Returns the number of bytes copied including the terminating NULL byte
+ *
+ * Note: dir and out must be PATH_MAX in length to avoid macOS fault
  */
 static size_t mkpath(const char *dir, const char *name, char *out)
 {
@@ -4710,12 +4712,18 @@ static bool run_cmd_as_plugin(const char *file, char *runfile, uchar flags)
 
 static bool plctrl_init(void)
 {
-       snprintf(g_buf, CMD_LEN_MAX, "nnn-pipe.%d", getpid());
+       size_t len;
+
        /* g_tmpfpath is used to generate tmp file names */
        g_tmpfpath[tmpfplen - 1] = '\0';
-       mkpath(g_tmpfpath, g_buf, g_pipepath);
+       len = xstrsncpy(g_pipepath, g_tmpfpath, TMP_LEN_MAX);
+       g_pipepath[len - 1] = '/';
+       len = xstrsncpy(g_pipepath + len, "nnn-pipe.", TMP_LEN_MAX - len) + len;
+       xstrsncpy(g_pipepath + len - 1, xitoa(getpid()), TMP_LEN_MAX - len);
        setenv(env_cfg[NNN_PIPE], g_pipepath, TRUE);
 
+       DPRINTF_S(g_pipepath);
+
        return EXIT_SUCCESS;
 }

Sorry, I guess I am sleepy. Ignore the above comment. Let’s try the next version.

Can repro with -O3 and -O2. -O1 works fine. As does -Os -march=native, which is what I would personally choose. Homebrew strips -O3 and replaces it with something to that effect, except with an explicit arch, e.g. nehalam. The cc shim that does that can be found at /usr/local/Homebrew/Library/Homebrew/shims/mac/super/cc (shims for other compilers and stuff can be found in the same folder). That’s why the Homebrew build works.

Aside: You can find the actual compiler invocation at ~/Library/Logs/Homebrew/nnn/01.make.cc if you install from source with brew: brew install -s nnn. It would look like

clang -pipe -w -Os -march=nehalem -std=c11 -o nnn src/nnn.c -lreadline -lncurses -isysroot/Library/Developer/CommandLineTools/SDKs/MacOSX11.0.sdk --sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX11.0.sdk -isystem/usr/local/include -isystem/Library/Developer/CommandLineTools/SDKs/MacOSX11.0.sdk/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers -I/usr/local/opt/readline/include -L/usr/local/opt/readline/lib -L/usr/local/lib -L/Library/Developer/CommandLineTools/SDKs/MacOSX11.0.sdk/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries -Wl,-headerpad_max_install_names

End of aside.

Not sure why even -O2 generates wrong code. Let me know if you want to chase this further, but I probably don’t have time for that until the weekend.