2012-12-18 24 views
2

我有一個C++程序作爲linux服務運行。某些程序的命令行選項只是簡單地在其配置文件中設置值,然後退出,然後需要重新啓動服務才能接收新配置。爲了使服務能夠繼續不間斷運行,其工作原理如下:C++:execv/execvp不使用現有的PID

  • 後臺服務在系統啓動時啓動
    • 後臺服務創建一個「配置看門狗」線程監視配置文件
  • 用戶從命令行運行「程序名選項」
    • 修改的配置文件
    • 程序的命令行實例退出
    • 後臺服務配置監視線程檢測更改配置,觸發重新啓動

當程序讀取新的配置,我打電話execv,使其保持在相同的進程空間後重新啓動原始實例,以便它可以繼續作爲服務進行管理。問題在於execv並不像預期的那樣運行,而是終止現有進程並重新啓動。由於PID不再匹配,如果我嘗試在此之後運行「service progname stop/restart」,它將無法正常工作,「停止」將使服務繼續運行,並且「重新啓動」將產生程序的重複實例。

我已經確認傳遞給execv的argv [0]是可執行文件的完整路徑,因此它不應該通過shell在PATH中搜索可執行文件(這也應該通過我使用execv而不是execvp)我已經讀過關於在其他應用程序中導致類似的問題。

+0

確實如此。所有可執行文件系列函數*替換*當前進程。另外,考慮使用傳統的SIGHUP通過線程觀察器。 – KAction

+0

是的,exec系列函數替換當前進程,但由於沒有創建新進程,因此不應更改PID。通過使用gdb連接到服務實例,我發現,當調用execv()時,gdb最初正確地遵循exec調用並打印「執行新程序/路徑/到/程序」,重新加載所有調試符號,但隨後使用「新」實例的PID分離並打印'從子進程XXX分叉後的分離「。在我的程序的任何地方都沒有對fork()的調用,所以看起來execv調用正在導致fork出於某種原因 – rdowell

+1

到目前爲止,消除的原則會導致我們相信你的程序會fork,並且你應該尋找叉子!如何更多的gdb-foo(例如「catch fork」,或者在exec之後設置「break fork」)。這裏可能還有其他一些設計問題!看門狗線程夠公平的;執行該服務是惡魔般的(!!);允許重複的實例本身就是一個問題(使用flock或lockf創建一個鎖文件)。 –

回答

0

發現問題,問題在於程序在啓動時使用daemon(),它在內部執行fork/exec,並且在重新啓動程序時它再次調用daemon()。在增強它以區分啓動/重新啓動並避免再次調用守護進程()後,問題得到解決。