從 scanadf 腳本呼叫時 pnmtops 子進程掛起

從 scanadf 腳本呼叫時 pnmtops 子進程掛起

幾年來我一直很高興地使用scanadf這些參數。-S script --script-wait

我的腳本名為 ,透過呼叫、透過管道傳輸,scan_perpage將影像資料轉換為 pdf 。pnmtopsps2pdf

然而最近(我懷疑自從我從 Fedora 17 更新到 19 以來),被調用的腳本掛起,因此scanadf掛起。該腳本在命令處掛起pnmtops。命令pnmtops本身正在等待其分叉的“子”pnmtops輸出過濾器完成,但它永遠不會完成。

scan_perpage直接在原始掃描器頁面輸出上運行腳本效果很好。直接運行pnmtops命令也可以正常工作。只有從scanadfvia運行時-S,腳本才會掛在 處pnmtops

版本:

# rpm -q --info sane-backends
Name        : sane-backends
Version     : 1.0.23
Release     : 13.fc19

# rpm -q --info sane-frontends
Name        : sane-frontends
Version     : 1.0.14
Release     : 16.fc19

# rpm -q --info netpbm
Name        : netpbm
Version     : 10.61.02
Release     : 5.fc19

這是我的腳本的輸出scan,它呼叫scanadf -vv

$ scan -o output.pdf
Scanning...
scanadf: value for --resolution is: 300
scanadf: scanning image of size 2544x3300 pixels at 1 bits/pixel
scanadf: acquiring gray frame
Started script `/usr/local/bin/scan_perpage' as pid=10902
Scanned document scan-0001
pnmtops: Input maxval is 1.  Postscript raster will have 1 bits per
sample, so maxval = 1
pnmtops: Image will be 610.56 points wide by 792.00 points high, left
edge 0.72 points from left edge of page, bottom edge 0.00 points from
bottom of page; NOT turned to landscape orientation
pnmtops: output filter spawned: pid 10904
pnmtops: Waiting for PID 10904 to exit
Scanned 1 pages
<the script hangs here>

這是掛起時的進程樹:

10897 32072 /bin/sh /usr/local/bin/scan -o output.pdf
10898 10897 scanadf -vvv -d fujitsu -S /usr/local/bin/scan_perpage
--script-wait --resolution 300 --mode Lineart -o scan-%04d
10902 10898 /bin/bash /usr/local/bin/scan_perpage scan-0001
10903 10902 pnmtops -verbose -imagewidth 8.5 -imageheight 11 scan-0001
10904 10903 pnmtops -verbose -imagewidth 8.5 -imageheight 11 scan-0001

進程 10904(分叉的pnmtops「輸出過濾器」)永遠不會完成。 strace 表明它正在等待「讀取」。

我不明白為什麼pnmtops在調用 via 時會掛起scanadf,但是當直接在同一文件上調用時,它工作得很好。

另外,如果pnmtops手動終止子進程,一切都會繼續,沒有任何問題。

答案1

來自 netpbm 維護者 Bryan Henderson:

我發現並修復了導致此症狀的錯誤。 [...] Netpbm 10.64.02 中已修復。

導致 Pnmtops 有時掛起有時不掛起的環境差異是開啟檔案的數量。如果在呼叫 Pnmtops 時開啟的檔案超過 10 個,則會發生掛起。

如果你關心病理是什麼:當傳送訊號給它的管道發出 EOF 訊號時,孩子就會退出。當管道發送端的文件描述符的每個副本都關閉時,就會發生這種情況。唯一應該存在的副本是父進程正在寫入資料的副本。但子進程必須繼承管道兩端的檔案描述符的副本。如果孩子沒有關閉其副本 傳送在管道的末端,子程序永遠不會在接收端看到 EOF,因此將永遠等待。

這意味著子進程必須關閉為其供電的管道發送端的副本。為了做到這一點,並解決其他一些類似的問題,子進程在啟動時嘗試關閉除了它實際使用的兩個檔案描述符之外的每個檔案描述符。但是 POSIX 沒有提供一種方法來了解開啟的檔案描述符列表,因此子進程只是盲目地關閉 0-9(不包括它需要的兩個),因為知道 Pnmtops 不會使用比這更多的檔案。錯誤在於該程式沒有考慮進程固有的檔案描述符。修復方法是 Pnmtops 在啟動時關閉檔案描述符 0-9,這樣它創建的任何管道的檔案描述符編號將在 0-9 範圍內,從而透過盲目的 0-9 關閉來關閉。

相關內容