g_spawn_async_with_pipes () の終了ステータス続き

以前 g_spawn_async_with_pipes() で終了ステータスを取得する方法を書きましたが、ステータス取得した後に waitpid(2) のマクロを使わないとよろしくなかったので追加。

ソースは以下の通りで、glibcが提供するヘッダを include します。waitpid(2) の man に書かれているマクロは、 sys/wait.h にあります。今回は、 WEXITSTATUS() マクロだけを使って、終了ステータスから整数に変換しています。このマクロを使用しないと、8bit左にシフトした値がstatusに入ります。

#include <glib.h>
#include <sys/types.h>
#include <sys/wait.h>

void
spawn_cb (GPid pid, gint status, GMainLoop *loop)
{
	g_print ("Exit %d\n", WEXITSTATUS (status));
	g_spawn_close_pid (pid);
	g_main_loop_quit (loop);
}

int
main (int argc, char* argv[])
{
	gchar *args[] = {"false"};
	GPid child_pid;
	GMainLoop *loop;

	g_type_init();
	g_spawn_async_with_pipes (NULL, args, NULL, 
					G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
					NULL, NULL, &child_pid, NULL, NULL, NULL, NULL);
	loop = g_main_loop_new (NULL, TRUE);
	g_child_watch_add (child_pid, spawn_cb, loop);
	g_main_loop_run (loop);
	return 0;
}

g_child_watch_add() の第2引数が GChildWatchFunc 型の関数で、これは、

void (*GChildWatchFunc) (GPid pid, gint status, gpointer user_data);

のような引数と返り値を持ちます。第2引数が終了ステータスで第3引数に g_child_watch_add()の第3引数が入ります。今回は GMainLoop 型のポインタを入れているので、 g_main_loop_quit() の引数で使用すると、 g_main_loop_run() で待ち状態になっているイベントループが終了します。

この第2引数の終了ステータスは、 waitpid(2) の終了ステータスと同じように扱う必要があるそうです。本来なら、 WIFEXITED() で正常終了を確かめた後に WEXITSTATUS() を使うと良いみたいです。