处理无效的文件句柄(可能还有其他无效对象)

Posted

技术标签:

【中文标题】处理无效的文件句柄(可能还有其他无效对象)【英文标题】:Dealing with invalid filehandles (and maybe other invalid objects too) 【发布时间】:2019-06-27 07:58:12 【问题描述】:

正如 Tom Browder 在 this issue 中指出的那样,如果命令行中提到的任何文件不存在,$*ARGFILES dynamic variable 可能包含无效的文件句柄。

for $*ARGFILES.handles -> $fh 
    say $fh;

将失败并出现X::AdHoc 异常(这可能也应该改进):

Failed to open file /home/jmerelo/Code/perl6/my-perl6-examples/args/no-file: No such file or directory

一旦将无效的文件句柄用于任何事情,就会出现问题。有没有办法在引发异常之前检查文件句柄是否有效?

【问题讨论】:

【参考方案1】:

您可以通过检查真实性或定义性没有 Failure 抛出来检查某事物是否为Failure

for $*ARGFILES.handles -> $fh 
    say $fh if $fh;  # check truthiness
    .say with $fh;   # check definedness + topicalization

如果你还想扔掉Failure所包含的Exception,那么你可以直接.throw它。

【讨论】:

还是同样的问题,在if $fh级别抛出。第二个更奇怪,因为它说“错误的文件描述符”。 嗨@jjmerelo 和丽兹。在.handles 中抛出异常。它没有达到-> $fh 绑定的程度,更不用说进入块并执行if 语句。我希望这只是IO::CatHandle 中某个地方的调整,以返回Failure 而不是抛出。但即使这是固定的,请参阅我对 Zoffix 提出的解决方案的回答,这很奇怪 A)他们建议了它(为什么不只是 for 循环?)和 B)它有一个奇怪的错误。 问题是.handles迭代器调用.next-handle其中unconditionally throws the Failure。【参考方案2】:

TL;DR我以为 Liz 搞定了,但似乎有一个错误,或者可能是呃。

一个错误?

看起来每当IO::CatHandle class's .handles method 到达一个按权利应该产生Failure 的句柄(延迟任何异常抛出)时,它会立即抛出一个异常(如果它只是被延迟或者可能会工作的那个异常东西坏了)。

这似乎是错误的或非常错误的。

见the exchange between Zoffix and Brad Gilbert and Zoffix's answer问题How should I handle Perl 6 $*ARGFILES that can't be read by lines()?

还有:

https://github.com/rakudo/rakudo/issues/1313

https://github.com/rakudo/rakudo/search?q=argfiles&type=Issues

https://github.com/rakudo/rakudo/search?q=cathandle&type=Issues

一个潜在的解决方法目前是另一个错误?

在讨论"Implement handler for failed open on IO::CatHandle"Zoffix++ 时,使用此代码作为解决方案关闭它:

.say for ($*ARGFILES but role 
    method next-handle 
        loop try return self.IO::CatHandle::next-handle
    
)

我看到 tbrowder 已将此问题作为相关问题的一部分重新打开,这是该 SO 要说的:

如果这可行,它至少是文档中$*ARGFILES var 的可用示例。

但是当我在6.d 中运行它(并看到6.c 的类似结果)时,无论输入是否有效,我都会得到:

say not yet implemented

(如果我 .put 或其他类似)。

这很疯狂,表明一些大胆的事情正在搞砸。

我已在 rt 和 gh/rakudo 问题中搜索“尚未实施”,但没有找到相关匹配项。

另一种解决方法?

Zoffix 显然打算将他们的代码作为永久解决方案,而不仅仅是一种变通方法。但不幸的是,它现在似乎根本不起作用。

目前为止我想出的最好的:

try $*ARGFILES andthen say $_    # $_ is a defined ArgFiles instance
                 orelse  say $!;   # $! is an error encountered inside the `try`

也许这是一个黑白的作品,它要么全部有效,要么没有一个解决方案。 (虽然我不相信它就是这样。)

文档对$*ARGFILES 的评价

$*ARGFILES 说它是一个实例

IO::ArgFiles 被记录为一个类

出于向后兼容性的原因而存在并且不提供任何方法。

所有功能都继承自

IO::CatHandle 副标题为

使用多个 IO 句柄,就好像它们是一个句柄一样

并将 doc'd 作为 is 的类

IO::Handle 副标题为

打开的文件或流

并作为一个不从任何其他类继承的类(因此默认为从Any 继承)或做任何角色。

因此,$*ARGFILES 是(在功能上与)IO::CatHandle 对象(功能的超集)IO::Handle 对象,具体来说:

IO::CatHandle 类提供了一种创建IO::Handle 的方法,该IO::Handle 可以无缝地从多个IO::HandleIO::Pipe 源收集输入。 IO::Handle 的所有方法都已实现,虽然尝试使用 write 方法将(当前)抛出异常,但 IO::CatHandle 可用于任何可以使用只读 IO::Handle 的地方。

探索the code for IO::CatHandle

(以后填写?)

【讨论】:

$*ARGFILES 没问题,它是 $*ARGFILES.handles 引发错误的那个。但在这种情况下,尝试可能是一个好方法。 谢谢。我两次严重偏离轨道(还有另一个与此无关的已删除答案,我可能永远不会透露。:))。 Anyhoo,答案重写。你接受这个答案对我来说还没有意义。您确定我的解决方法对您或 Tom 有效吗? 您不必透露它。如果一个人有足够的声望点,他们仍然可以阅读它。 .next-handle throws the Failure as soon as it sees it @BradGilbert Thx 了解有关揭示的信息。是的,您链接的代码显然是问题所在。你和 Zoffix 已经根据我在 bdfoy 发布的 SO 上链接的交流讨论了它,对吧? (我正在尝试正确理解 Zoffix 的观点与您的观点之间的优缺点。)我在答案的 Ugh 部分中包含的链接中列出的错误是否已经充分涵盖了问题,或者你认为我们需要发布另一个问题吗?与此同时,您是否对 A potential workaround is current is another bug? 部分中奇怪的 not yet implemented 消息有任何线索? 据我所知,删除 .throw 不会导致任何以前工作的代码突然失败。它应该使 Zoffix 的上述代码有效,它应该使 lizmat 的代码也有效。问题是每个人都在编写代码时期望它是失败而不是异常。那么为什么不这样做呢?

以上是关于处理无效的文件句柄(可能还有其他无效对象)的主要内容,如果未能解决你的问题,请参考以下文章

securecrtYmodem句柄无效

win10刻盘时出现无效的文件句柄如何修复?

linux删除文件后空间无法释放?lsof没有结果。重启无效。请问各位高手还有别的办法吗?

当我运行下面的代码时,我正在获取句柄无效,它需要一个字符串并将其传递给远程批处理文件

错误6句柄在Windows上写入文件无效[关闭]

DOS/sqlplus“句柄无效”错误?