2017-07-27 60 views
6

考慮下面的代碼:在execl()調用之後退出(0)是否有意義?

close(channel_data->pty_master); 

if (login_tty(channel_data->pty_slave) != 0) // new terminal session 
{ 
    exit(1); // fail 
} 

execl("/bin/sh", "sh", mode, command, NULL); // replace process image 
exit(0); 

execl()文檔,當前的進程映像被替換和呼叫僅返回上的錯誤。

但是,如果過程映像被替換,爲什麼在致電execl()之後致電exit()

回答

3

在某些exec(3)函數之後調用exit是合理的,因爲它們可能會失敗(例如,當execve(2)失敗時)。 execve(2)頁面列出了一些故障原因。

最好是exit(EXIT_FAILURE)或其他一些(非0)退出代碼(傳統上使用127或126這樣的高退出代碼來分隔exec的故障與它運行的程序中的錯誤),我建議在exit之前撥打perror。由於explained by PSKocick有很好的理由叫_exit(但他的論點可以顛倒,人們會想運行atexit和標準fflush通過使用exit代替)。

在你的情況下,失敗的可能性不大,但不過想象一下,如果一些其他進程已取消/bin/sh(例如系統管理員使運行在根目錄/bin/rm -rf .,或/bin/,也許在一些其他的終端窗口的愚蠢的錯誤)。

仍然是execve也可以當系統資源失敗(暫時的)枯竭,e.g爲

ENOMEM沒有足夠的內核內存可用。

而且(在極少數情況下)這可能發生在/bin/sh;

順便說一句,您的exec用法可能會失敗(與E2BIG)如果(由於錯誤)command是一百萬個非空字節的字符串。

作爲一般編碼規則,應檢查所有重要的system calls與失敗。

+0

在這種情況下,「失敗」究竟意味着什麼? – Shuzheng

+0

這意味着您嘗試運行的程序無法啓動,例如如果/ bin/sh不存在,或者它沒有適當的執行權限,或者系統不允許你運行程序(例如,你遇到了一些系統限制或策略,不允許你創建更多的進程 – nos

+1

@Shuzheng'exec()'family函數可能會失敗,原因很多,但結果是一樣的:當前進程的圖像不會被替換,並且會設置'errno',因此代碼放在'exec * ()'call will be executed。 – Geographer

1

但是,如果在過程映像被替換後調用execl()後爲什麼調用exit()?

正如你所說,execl()只在錯誤的回報:

execl("/bin/sh", "sh", mode, command, NULL); // replace process image 
exit(0); 

在上面的代碼,exit()被稱爲只有在execl()調用失敗。


由於Jonathan Leffler suggested in his comment它可能是一個非常好的主意,返回其它的值大於,因爲零表示成功和代碼確實失敗如果程序的控制流曾達到的exit()通話在上面的代碼中。

+1

0的退出狀態表示'成功' - 但代碼失敗 –

4

執行調用可能失敗。一個常見的結語是:

perror("Some eror message"); 
_exit(127); /*or _exit(1); (127 is what shells return) */ 

你通常會運行_exit而非exit這裏,以跳過atexit掛鉤和stdio緩衝區刷新。

+0

*'一個普通的結語將會是* * - 我認爲這就是爲什麼在代碼中使用註釋來解釋技術是不好的風格,請記住,有時候這肯定會被複制;) – Wolf

3

您會想撥exit,因爲您沒有對exec程序提出疑問,而且您通常不希望該進程因爲沒有運行您希望運行的程序而停留。由於execl僅在失敗時返回,因此無需檢查退貨狀態。

在很多情況下,打印錯誤消息以查明失敗原因也很有意義。您還應該使用非0的退出代碼。非零退出代碼用於指示異常退出,並且父進程在調用wait時可以捕獲該代碼。

execl("/bin/sh", "sh", mode, command, NULL); 
perror("command failed"); 
exit(1); 

所以,是的,是有意義的CAL exit,但不一定exit(0)

相關問題