我有(有)一些 Ruby 代碼,由于歷史原因,它們本質上是(曾經)
Dir.mktmpdir do |dir|
path_list = something_which_creates_files_in(dir)
path_list.each(&:delete)
end
有時我會從這段代碼中得到(得到)例外:
Errno::ENOENT: No such file or directory @ dir_s_rmdir - /tmp/d2..4w/file.csv
:
/path/to/source.rb:124:in `unlink'
/path/to/source.rb:124:in `delete'
/path/to/source.rb:124:in `each'
:
/usr/lib/ruby/2.5.0/tmpdir.rb:93:in `mktmpdir'
:
所以在我看來,我對塊末尾路徑串列的“清理”并不完全同步,(某些)檔案在完成后仍然存在,然后mktmpdir洗掉臨時目錄,以便異步( ?)unlink失敗,它的目標已經消失。這是一個合理的解釋嗎?
這更像是一個學術問題。這種行為讓我感到困惑。只需洗掉清理 ( path_list.each(&:delete)) 并將洗掉保留到Dir.mktmpdir似乎可以停止這些例外。
如果它有所作為,那就是在 Linux 上運行的 Ruby 2.5 (MRI)。
uj5u.com熱心網友回復:
你的假設似乎是正確的。
如果您檢查來源,File.unlink您可以看到以下內容:
static VALUE
rb_file_s_unlink(int argc, VALUE *argv, VALUE klass)
{
return apply2files(unlink_internal, argc, argv, 0);
}
這unlink_internal是一件微不足道的事情(只是系統呼叫的一個薄包裝?),但有趣的是apply2files. 您可以在那里看到以下呼叫:
...
rb_thread_call_without_gvl(no_gvl_apply2files, aa, RUBY_UBF_IO, 0);
...
哪里aa是一些花哨的結構,其中包含一個指向我們想要應用的東西的指標 -unlink在我們的例子中。
這個函式的名字很自我描述,但是原始碼也包含一些檔案,所以我們可以參考它:
/*
* rb_thread_call_without_gvl - permit concurrent/parallel execution.
* rb_thread_call_without_gvl2 - permit concurrent/parallel execution
* without interrupt process.
...
所以從我所看到的(免責宣告:沒有對源代碼進行真正仔細的分析:))有問題的塊中的洗掉1)確實同時發生并且2)沒有GIL“保護” - 所以“驚喜”是可能的如果嘗試洗掉臨時檔案兩次(第一次顯式洗掉,第二次在mktmpdir塊退出時隱式洗掉??)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/410171.html
標籤:
上一篇:讓這些影像在Vue.js中呈現
