Scanner

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

  • November 12, 2013

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

我的腳本名為scan_perpage,通過呼叫 ,通過pnmtops管道將圖像數據轉換為 pdf ps2pdf

但是最近(我懷疑自從我從 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子程序被手動殺死,一切都會繼續進行,沒有任何問題。

來自 netpbm 的維護者 Bryan Henderson:

我發現並修復了導致此症狀的錯誤。

$$ … $$修復在 Netpbm 10.64.02 中。 導致 Pnmtops 有時掛起有時不掛起的環境差異是打開文件的數量。如果呼叫 Pnmtops 時打開的文件超過 10 個,則會發生掛起。

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

這意味著孩子必須關閉正在餵牠的管道發送端的副本。為了做到這一點,並修復一些其他類似的問題,孩子在啟動時嘗試關閉除了它實際使用的兩個文件描述符之外的每個文件描述符。但是 POSIX 沒有提供知道打開文件描述符列表的方法,所以孩子只是盲目地關閉 0-9(不包括它需要的兩個),因為知道 Pnmtops 不會使用比這更多的文件。錯誤在於程序沒有考慮到程序出生時的文件描述符。修復是 Pnmtops 在啟動時關閉文件描述符 0-9,以便它創建的任何管道都將具有 0-9 範圍內的文件描述符編號,從而被盲目的 0-9 關閉關閉。

引用自:https://unix.stackexchange.com/questions/93384