我写了个宏,让 hosts 文件里的坏行被记录下来,加载继续往下走。完整代码如下。
(defmacro with-lenient-parse ((&key (log t)) &body body)
`(handler-bind ((missing-field
(lambda (c)
(when ,log
(format *error-output* "skipping: ~A~%" c))
nil))
(bad-port
(lambda (c)
(when ,log
(format *error-output* "warn: ~A~%" c))
nil)))
,@body))
parse-line 有一个 skip-line 重启,但我不确定有没有东西会调用它。输入格式是 name addr [port],每行一台主机,我用 sh run.sh 运行。
文件里有 web-02(没有 addr)时,stderr 上会出现 skipping: line 2: missing addr。然后 SBCL 带着同一个 missing-field 错误进入调试器,脚本就挂了。我以为从 handler 里返回就会让 parse-line 对这一行返回 nil,对吧?看来不是。
我把 web-02 那行删了才继续往下。现在得到 warn: line 4: bad port abc,接着 privileged-p 里报类型错误,说 NIL 不是 NUMBER 类型。那个函数跟解析毫无关系。端口条件只是对 warning 子类的一次普通 signal,我写的东西里没有哪处把它当成致命的。
这是两个 bug,还是对 handler 如何挂接的同一个误解?这个宏到底向调用方承诺了什么?我是凭对终端记录的印象写的,所以没法贴完整的回溯信息。
从英语翻译·查看原文I wrote a macro so a bad line in a hosts file gets logged and the load carries on. This is the whole thing:
(defmacro with-lenient-parse ((&key (log t)) &body body)
`(handler-bind ((missing-field
(lambda (c)
(when ,log
(format *error-output* "skipping: ~A~%" c))
nil))
(bad-port
(lambda (c)
(when ,log
(format *error-output* "warn: ~A~%" c))
nil)))
,@body))
parse-line has a skip-line restart, but I'm not sure anything ever invokes it. The input is name addr [port], one host per line, and I run it with sh run.sh.
With web-02 (no addr) in the file, I get skipping: line 2: missing addr on stderr. Then SBCL drops into the debugger with that same missing-field error and the script dies. I figured returning from the handler would make parse-line return nil for that line, right? Apparently not.
I deleted the web-02 line to get past it. Now I get warn: line 4: bad port abc, and then a type error in privileged-p saying NIL is not of type NUMBER. That function has nothing to do with parsing. The port condition is a plain signal of a warning subclass, and nothing I wrote treats it as fatal.
Is this two bugs or one misunderstanding of how the handler hooks in? What is the macro actually promising the caller? I'm going from memory of the transcript, so I can't paste the full backtrace.