温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

使用strace查找Emacs启动阻塞的原因有哪些

发布时间:2021-10-23 11:34:15 阅读:123 作者:小新 栏目:系统运维
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章给大家分享的是有关使用strace查找Emacs启动阻塞的原因有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

由于使用了 spacemacs 的配置,配置上比较复杂,不太想通过实验缩减配置的方式来摸索出问题的地方。刚好最近在学习使用 strace 工具,因此决定使用 strace 来看看 Emacs 到底卡在哪里。

strace emacs --fg-daemon

输出的内容特别多,这里只截取卡顿前的部分内容

readlinkat(AT_FDCWD"/home"0x7ffd1d3abb501024= -1 EINVAL (无效的参数)readlinkat(AT_FDCWD"/home/lujun9972"0x7ffd1d3abf001024= -1 EINVAL (无效的参数)readlinkat(AT_FDCWD"/home/lujun9972/.emacs.d"0x7ffd1d3ac2b01024= -1 EINVAL (无效的参数)readlinkat(AT_FDCWD"/home/lujun9972/.emacs.d/elpa"0x7ffd1d3ac6601024= -1 EINVAL (无效的参数)readlinkat(AT_FDCWD"/home/lujun9972/.emacs.d/elpa/exec-path-from-shell-20180323.1904"0x7ffd1d3aca101024= -1 EINVAL (无效的参数)readlinkat(AT_FDCWD"/home/lujun9972/.emacs.d/elpa/exec-path-from-shell-20180323.1904/exec-path-from-shell.elc"0x7ffd1d3acdc01024= -1 EINVAL (无效的参数)lseek(7-2655SEEK_CUR)               = 1441read(7"\n(defvar exec-path-from-shell-de"...4096= 4096lseek(75537SEEK_SET)                = 5537lseek(75537SEEK_SET)                = 5537lseek(75537SEEK_SET)                = 5537lseek(75537SEEK_SET)                = 5537lseek(75537SEEK_SET)                = 5537lseek(75537SEEK_SET)                = 5537brk(0x7507000)                          = 0x7507000lseek(75537SEEK_SET)                = 5537lseek(75537SEEK_SET)                = 5537lseek(75537SEEK_SET)                = 5537read(7"230\\205\26\0\t\22\\307\\310\t!\vC\\\"\\211\24\\2"...4096= 2430lseek(77967SEEK_SET)                = 7967lseek(77967SEEK_SET)                = 7967lseek(77967SEEK_SET)                = 7967lseek(77967SEEK_SET)                = 7967read(7""4096)                       = 0close(7)                                = 0getpid()                                = 10818faccessat(AT_FDCWD"/home/lujun9972/bin/printf"X_OK= -1 ENOENT (没有那个文件或目录)faccessat(AT_FDCWD"/usr/local/sbin/printf"X_OK= -1 ENOENT (没有那个文件或目录)faccessat(AT_FDCWD"/usr/local/bin/printf"X_OK= -1 ENOENT (没有那个文件或目录)faccessat(AT_FDCWD"/usr/bin/printf"X_OK= 0stat("/usr/bin/printf", {st_mode=S_IFREG|0755, st_size=51176...}) = 0openat(AT_FDCWD"/dev/null"O_RDONLY|O_CLOEXEC= 7faccessat(AT_FDCWD"/proc/5070/fd/."F_OK= 0faccessat(AT_FDCWD"/proc/5070/fd/."F_OK= 0faccessat(AT_FDCWD"/bin/bash"X_OK)  = 0stat("/bin/bash", {st_mode=S_IFREG|0755, st_size=903440...}) = 0pipe2([89], O_CLOEXEC)                = 0rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8= 0vfork()                                 = 10949rt_sigprocmask(SIG_SETMASK, [], NULL8= 0close(9)                                = 0close(7)                                = 0read(8"bash: \346\227\240\346\263\225\350\256\276\345\256\232\347\273\210\347\253\257\350\277\233\347\250\213\347\273"...16384= 74read(8"bash: \346\255\244 shell \344\270\255\346\227\240\344\273\273\345\212\241\346\216\247\345"...16310= 35read(8"setterm: \347\273\210\347\253\257 xterm-256color \344"...16275= 51read(8"Couldn't get a file descriptor r"...16224= 56read(8"bash: [: \357\274\232\351\234\200\350\246\201\346\225\264\346\225\260\350\241\250\350\276\276\345\274"...16168= 34read(8"Your display number is 0\n"16134= 25read(8"Test whether fcitx is running co"...16109= 53read(8"Fcitx is running correctly.\n\n==="...16056= 87read(8"Launch fbterm...\n"15969)    = 17read(8"stdin isn't a tty!\n"15952)  = 19read(8"__RESULT\0/home/lujun9972/bin:/ho"...15933= 298read(80x7ffd1d39ce9d15635)          = ? ERESTARTSYS (To be restarted if SA_RESTART is set)--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=10949, si_uid=1000, si_status=0, si_utime=10, si_stime=7---rt_sigreturn({mask=[]})                 = -1 EINTR (被中断的系统调用)read(8""15635)                      = 0wait4(10949, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0NULL= 10949close(8)                                = 0getpid()                                = 10818faccessat(AT_FDCWD"/home/lujun9972/bin/printf"X_OK= -1 ENOENT (没有那个文件或目录)faccessat(AT_FDCWD"/usr/local/sbin/printf"X_OK= -1 ENOENT (没有那个文件或目录)faccessat(AT_FDCWD"/usr/local/bin/printf"X_OK= -1 ENOENT (没有那个文件或目录)faccessat(AT_FDCWD"/usr/bin/printf"X_OK= 0stat("/usr/bin/printf", {st_mode=S_IFREG|0755, st_size=51176...}) = 0openat(AT_FDCWD"/dev/null"O_RDONLY|O_CLOEXEC= 7faccessat(AT_FDCWD"/proc/5070/fd/."F_OK= 0faccessat(AT_FDCWD"/proc/5070/fd/."F_OK= 0faccessat(AT_FDCWD"/bin/bash"X_OK)  = 0stat("/bin/bash", {st_mode=S_IFREG|0755, st_size=903440...}) = 0pipe2([89], O_CLOEXEC)                = 0rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8= 0vfork()                                 = 11679rt_sigprocmask(SIG_SETMASK, [], NULL8= 0close(9)                                = 0close(7)                                = 0read(8"setterm: \347\273\210\347\253\257 xterm-256color \344"...16384= 51read(8"Couldn't get a file descriptor r"...16333= 56read(8"/home/lujun9972/.bash_profile: \347"...16277= 72read(8"Your display number is 0\nTest wh"...16205= 78read(8"Fcitx is running correctly.\n\n==="...16127= 104read(8"stdin isn't a tty!\n"16023)  = 19read(8"__RESULT\0b269cd09e7ec4e8a115188c"...16004= 298read(80x7ffd1d39cba615706)          = ? ERESTARTSYS (To be restarted if SA_RESTART is set)--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=11679, si_uid=1000, si_status=0, si_utime=1, si_stime=1---rt_sigreturn({mask=[]})                 = -1 EINTR (被中断的系统调用)read(8,

很容易就可以看出,当 Emacs 卡顿时,它在尝试从 8 号文件句柄中读取内容。

那么 8 号文件句柄在哪里定义的呢?往前看可以看到:

pipe2([89], O_CLOEXEC)                = 0rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8= 0vfork()                                 = 11679rt_sigprocmask(SIG_SETMASK, [], NULL8= 0close(9)                                = 0

可以推测出,Emacs 主进程 fork 出一个子进程(进程号为 11679),并通过管道读取子进程的内容。

然而,从

--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=11679, si_uid=1000, si_status=0, si_utime=1, si_stime=1} ---rt_sigreturn({mask=[]})                 = -1 EINTR (被中断的系统调用)read(8,

可以看出,实际上子进程已经退出了(父进程收到 SIGCHLD 信号),父进程确依然在尝试从管道中读取内容,导致的阻塞。

而且从

read(8"setterm: \347\273\210\347\253\257 xterm-256color \344"..., 16384) = 51read(8"Couldn't get a file descriptor r"..., 16333) = 56read(8"/home/lujun9972/.bash_profile: \347"..., 16277) = 72read(8"Your display number is 0\nTest wh"..., 16205) = 78read(8"Fcitx is running correctly.\n\n==="..., 16127) = 104read(8"stdin isn't a tty!\n"16023)  = 19read(8"__RESULT\0b269cd09e7ec4e8a115188c"..., 16004) = 298read(80x7ffd1d39cba615706)          = ? ERESTARTSYS (To be restarted if SA_RESTART is set)

看到,子进程的输出似乎是我的交互式登录 bash 启动时的输出(加载了 .bash_profile

在往前翻发现这么一段信息:

readlinkat(AT_FDCWD, "/home"0x7ffd1d3abb501024) = -1 EINVAL (无效的参数)readlinkat(AT_FDCWD, "/home/lujun9972"0x7ffd1d3abf001024) = -1 EINVAL (无效的参数)readlinkat(AT_FDCWD, "/home/lujun9972/.emacs.d"0x7ffd1d3ac2b01024) = -1 EINVAL (无效的参数)readlinkat(AT_FDCWD, "/home/lujun9972/.emacs.d/elpa"0x7ffd1d3ac6601024) = -1 EINVAL (无效的参数)readlinkat(AT_FDCWD, "/home/lujun9972/.emacs.d/elpa/exec-path-from-shell-20180323.1904"0x7ffd1d3aca101024) = -1 EINVAL (无效的参数)readlinkat(AT_FDCWD, "/home/lujun9972/.emacs.d/elpa/exec-path-from-shell-20180323.1904/exec-path-from-shell.elc"0x7ffd1d3acdc01024) = -1 EINVAL (无效的参数)lseek(7-2655, SEEK_CUR)               = 1441read(7"\n(defvar exec-path-from-shell-de"..., 4096) = 4096

这很明显是跟 exec-path-from-shell 有关啊。

通过查看 exec-path-from-shell 的实现,发现 exec-path-from-shell 的实现原理是通过实际调启一个 shell,然后输出 PATH 和 MANPATH 的值的。 而且对于 bash 来说,默认的启动参数为 -i -l(可以通过exec-path-from-shell-arguments来设置)。也就是说 bash 会作为交互式的登录shell来启动的,因此会加载 .bash_profile 和 .bashrc

既然发现跟 exec-path-from-shell 这个包有关,而且据说这个包对 Linux 其实意义不大,那不如直接禁用掉好了。

dotspacemacs-excluded-packages '(exec-path-from-shell)

再次重启Emacs,发现这次启动速度明显快了许多了。

感谢各位的阅读!关于“使用strace查找Emacs启动阻塞的原因有哪些”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://linux.cn/article-11401-1.html

AI

开发者交流群×