今天在在測試c++ network programing中例子8.2時,碰到了一個問題:發現ACE_Processwait得到的child的exit_code不正確,測試的平台是linux 2.6.16,ACE的版本是6.0.0.
寫了個簡單的測試代碼如下:
#include <ace/ACE.h>#include <ace/OS_NS_stdlib.h>#include <ace/Process.h>#include <ace/Basic_Types.h>int main(intargc, ACE_TCHAR* argv[]){ int loop = 10; if (1 == argc) { ACE_Process_Options options; for (int i = 1; i <= loop; i++) { options.command_line("%s %d", argv[0], i); ACE_Process child; pid_t pid = child.spawn(options); child.wait(); ACE_DEBUG((LM_DEBUG, "child %d exit code=%d\n", i, child.exit_code() )); } } // spwan出來的process else { ACE_OS::exit(ACE_OS::atoi(argv[1])); }}
測試得出的結果很奇怪:不是設想中的1到10。
百思不得其解,萬能google發現也有其他人在red hat上碰到類似的問題,於是按照上面說的,把exit_code()改成return_value()這個api,再測試一把,結果就正確了:
找到ACE的源碼,找到exit_code()和return_value()這兩個api的地方,發現了源碼作者在exit_code上特別註明了:“This value is system dependent”。而對於書上的例子,我自己猜測應該在win下能正常運行,只是linux下的傳回值(raw exit status)跟win下不一樣,但是return_value應該都是一致的。
/// Return the Process' exit code. This method returns the raw/// exit status returned from system APIs (such as <wait> or/// <waitpid>). This value is system dependent.ACE_exitcode exit_code (void) const;/// Return the Process' return value. This method returns the/// actual return value that a child process returns or <exit>s.int return_value (void) const;
事後請教了ACE大牛同事,經指點,修改上面的測試程式如下:
ACE_exitcode status;child.wait(&status);if(WIFEXITED(status)){ACE_DEBUG((LM_DEBUG, "child %d exit code=%d\n", i, WEXITSTATUS(status)));}
上面這種用法是linux下擷取子進程傳回值的常規寫法,測試也ok。
查閱ACE的源碼,找到注釋說明:
// Evaluates to a non-zero value if status was returned for a child// process that terminated normally. 0 means status wasn't// returned.# if !defined (WIFEXITED)# define WIFEXITED(stat) 1# endif /* WIFEXITED */// If the value of WIFEXITED(stat) is non-zero, this macro evaluates// to the exit code that the child process exit(3C), or the value// that the child process returned from main. Peaceful exit code is// 0.# if !defined (WEXITSTATUS)# define WEXITSTATUS(stat) stat# endif /* WEXITSTATUS */
總結如下:
1. ACE的代碼相當龐大,不同版本的代碼和api差別不小,碰到一些不清楚的地方,最好先查閱源碼,源碼中的注釋很重要;
2. ACE號稱跨平台,但是實際上OS底層相關的部分,還是很難做到盡善盡美的,倒不是說ACE代碼寫的不好,而是我們在應用的過程中要結合實際平台多加考慮;