今天在在测试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代码写的不好,而是我们在应用的过程中要结合实际平台多加考虑;