qt 4.7.1이상하네요.
뭐 저는 qt 완전 초보고 아는게 하나없지만
이번에 노키아에서 여는 Qt Conference - Seoul 2010(12월 14일)
(여기 관련 글타래가 있네요 , http://kldp.org/node/119396)도 있고 해서
최근에 발표된 Qt 4.7.1을 우분투 제 데스크탑에 컴파일 설치해봤습니다.
뭐 컴파일 과정에 몇가지 문제(이건 따로 다루죠)가 있긴 했지만 잘 컴파일되었고
설치도 끝나 kde 등 의존 프로그램들을 재컴파일해주었습니다.
그 과정에서 조금 심각해 보이는 문제가 나타나 글을 적어봅니다.
qt의 빌딩 툴 중에 qdbuscpp2xml, qdbusxml2cpp 이 있는데 이름이
나타내듯 컴파일과정에서 실시간으로 헤더나 소스파일에서 xml파일을 만들고
반대로 xml파일이 주어지면 헤더나 소스를 만들어 내는 도구죠.
이 툴중 qdbuscpp2xml은 화면(표준출력)으로 결과를 보이거나
-o옵션으로 결과 파일을 만듭니다.
예컨대
qdbuscpp2xml test.cpp > test.xml
또는
qdbuscpp2xml test.cpp -o 5.xml
그런데 새로 설치한 Qt 4.7.1라이브러리로 새로 링크하기위해 kde 라이브러리나 프로그램들을
재컴파일하는 과정에 위 도구가 사용되는데 ,예를 들어
/usr/bin/qdbuscpp2xml /media/sdc1/kdebase-4.2.2/apps/keditbookmarks/toplevel.h > /media/sdc1/kdebase-4.2.2/obj-i686-linux-gnu/apps/keditbookmarks/org.kde.keditbookmarks.xml
/usr/bin/qdbusxml2cpp -m -p toplevel_interface /media/sdc1/kdebase-4.2.2/obj-i686-linux-gnu/apps/keditbookmarks/org.kde.keditbookmarks.xml
이렇게 말이죠.
얼핏 아무 문제없어 보이지만 이런 과정을 거치는
모든 kde프로그램이 모두다 같은 에러로 빌드가 멈춥니다.
예컨대
[ 40%] Generating org.kde.keditbookmarks.xml
cd /media/sdc1/kdebase-4.2.2/obj-i686-linux-gnu/apps/keditbookmarks && /usr/bin/qdbuscpp2xml /media/sdc1/kdebase-4.2.2/apps/keditbookmarks/toplevel.h > /media/sdc1/kdebase-4.2.2/obj-i686-linux-gnu/apps/keditbookmarks/org.kde.keditbookmarks.xml
qdbuscpp2xml: exit code 0 from moc. Aborting <== !!!!!!!!!!!
QProcess: Destroyed while process is still running.
make[2]: *** [apps/keditbookmarks/org.kde.keditbookmarks.xml] error 1
사용된 toplevel.h 파일은 문제가 없습니다.
사용된 qdbuscpp2xml(4.7.1버젼에서 새로 설치한)파일에 무슨 문제가있는걸까요?
qdbuscpp2xml은 내부적으로 /usr/bin/moc-qt4을 호출해 입력 데이타를 처리하고
그 결과를 화면에 출력하게 되어 있는데 이게 결과를 처리하기도 전에 이유없이 exit해 버려서
그에 따라 파일 크기가 0인 아무내용없는 org.kde.keditbookmarks.xml 파일을 만들어 내
전체 빌드가 망가집니다.
간단한 예제 코드를 써서 알아보죠.
[/media/sdc2/test-qt-bin]$ more test.cpp #include <QString> #include <QDBusAbstractAdaptor> class TestAdapter : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "tld.example.Foo") public Q_SLOTS: void method(QString foo); };
이 코드를 처리해서 xml 파일로 만들기 위해 아래 명령을 하면
이 작은 파일에서조차 기대와는 달리 작동하지 않습니다.
$ qdbuscpp2xml test.cpp > test.xml qdbuscpp2xml: exit code 0 from moc. Aborting QProcess: Destroyed while process is still running. $ ls -al test.xml -rw-r--r-- 1 s4ndy s4ndy 0 2010-11-24 18:24 test.xml $ qdbuscpp2xml test.cpp -o test.xml qdbuscpp2xml: exit code 0 from moc. Aborting QProcess: Destroyed while process is still running. $ ls -al test.xml -rw-r--r-- 1 s4ndy s4ndy 0 2010-11-24 18:24 test.xml
strace로 추적해보면 /usr/bin/moc-qt4 도 잘 찾고
입력 파일을 읽어서 잘처리하고 있지만 이렇게 처리된 결과를 옵션에 따라
화면이나 파일로 보낼때 마지막 순간에 이유없이 프로세스간 데이타 전달이 끊기는게 보입니다.
왜 이런 일이 생기는 걸까요?
$strace -ff qdbuscpp2xml test.cpp > test.xml set_tid_address(0xb6f4e708) = 27818 sched_getparam(27818, { 0 }) = 0 sched_getscheduler(27818) = 0 (SCHED_OTHER) clock_getres(CLOCK_MONOTONIC, {0, 999848}) = 0 sched_get_priority_min(SCHED_OTHER) = 0 sched_get_priority_max(SCHED_OTHER) = 0 sched_get_priority_max(SCHED_OTHER) = 0 pipe([3, 4]) = 0 fcntl64(3, F_SETFD, FD_CLOEXEC) = 0 fcntl64(4, F_SETFD, FD_CLOEXEC) = 0 readlink("/proc/27818/exe", "/usr/bin/qdbuscpp2xml", 4096) = 21 lstat64("/usr/bin/qdbuscpp2xml", {st_mode=S_IFREG|0755, st_size=38808, ...}) = 0 pipe([5, 6]) = 0 fcntl64(5, F_SETFD, FD_CLOEXEC) = 0 fcntl64(6, F_SETFD, FD_CLOEXEC) = 0 fcntl64(5, F_GETFL) = 0 (flags O_RDONLY) fcntl64(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 fcntl64(6, F_GETFL) = 0x1 (flags O_WRONLY) fcntl64(6, F_SETFL, O_WRONLY|O_NONBLOCK) = 0 rt_sigaction(SIGCHLD, {0xb74ea4f0, [], SA_NOCLDSTOP}, {SIG_DFL}, 8) = 0 open("test.cpp", O_RDONLY|O_LARGEFILE|0x80000) = 7 fcntl64(7, F_SETFD, FD_CLOEXEC) = 0 fstat64(7, {st_mode=S_IFREG|0644, st_size=231, ...}) = 0 brk(0x8094000) = 0x8094000 fstat64(7, {st_mode=S_IFREG|0644, st_size=231, ...}) = 0 read(7, "#include <QString>\n#include <QDB"..., 16384) = 231 read(7, "", 16153) = 0 clone(Process 27819 attached child_stack=0xb6c9e4b4, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb6c9ebd8, {entry_number:6, base_addr:0xb6c9eb90, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb6c9ebd8) = 27819 [pid 27818] pipe([8, 9]) = 0 [pid 27818] fcntl64(8, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] fcntl64(9, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] pipe([10, 11]) = 0 [pid 27818] fcntl64(10, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] fcntl64(11, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] pipe([12, 13]) = 0 [pid 27818] fcntl64(12, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] fcntl64(13, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] pipe([14, 15]) = 0 [pid 27818] fcntl64(14, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] fcntl64(15, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] pipe([16, 17]) = 0 [pid 27818] fcntl64(16, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] fcntl64(17, F_SETFD, FD_CLOEXEC) = 0 [pid 27818] clone(Process 27820 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb6f4e708) = 27820 [pid 27820] execve("/usr/bin/moc-qt4", ["/usr/bin/moc-qt4", "test.cpp"], [/* 57 vars */]) = 0 [pid 27820] open("test.cpp", O_RDONLY) = 3 [pid 27820] read(3, "#include <QString>\n#include <QDB"..., 16384) = 231 [pid 27820] read(3, "", 12288) = 0 [pid 27820] read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\5\0\0\0\5\0\0"..., 4096) = 380 [pid 27820] read(3, "\nKST-9\n", 4096) = 7 [pid 27820] write(1, "/*******************************"..., 2461) = 2461 [pid 27820] exit_group(0) = ? Process 27820 detached <======!!!!! [pid 27818] ioctl(10, FIONREAD <unfinished ...> [pid 27819] <... select resumed> ) = ? ERESTARTNOHAND (To be restarted) [pid 27819] --- SIGCHLD (Child exited) @ 0 (0) --- <======!!!!! [pid 27819] write(6, "\0", 1) = 1 [pid 27819] read(5, "\0", 1) = 1 [pid 27819] write(17, "\0", 1) = 1 [pid 27819] select(6, [5], NULL, NULL, NULL <unfinished ...> [pid 27818] <... ioctl resumed> , [2461]) = 0 [pid 27818] read(10, "/*******************************"..., 2461) = 2461 [pid 27818] read(16, "\0", 1) = 1 [pid 27818] waitpid(27820, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG) = 27820 [pid 27818] ioctl(-1, FIONREAD, [0]) = -1 EBADF (Bad file descriptor) [pid 27818] ioctl(-1, FIONREAD, [0]) = -1 EBADF (Bad file descriptor) [pid 27818] close(17) = 0 [pid 27818] close(16) = 0 [pid 27818] close(7) = 0 [pid 27818] write(1, "<!DOCTYPE node PUBLIC \"-//freede"..., 299) = 299 [pid 27818] open("/proc/stat", O_RDONLY) = 7 [pid 27818] write(6, "@", 1 <unfinished ...> [pid 27819] <... select resumed> ) = 1 (in [5]) [pid 27819] read(5, "@", 1) = 1 [pid 27819] close(8) = 0 [pid 27819] close(11) = 0 [pid 27819] _exit(0) = ? Process 27819 detached <... write resumed> ) = 1 close(6) = 0 close(5) = 0 rt_sigaction(SIGCHLD, {SIG_DFL}, {0xb74ea4f0, [], SA_NOCLDSTOP}, 8) = 0 exit_group(0) = ? Process 27818 detached
좀더 알기쉽게 strace 내에서 출력을 파일로 보내지 않고 strace -ff qdbuscpp2xml test.cpp 로 그냥 화면으로 보내보면 xml 파일이 화면에 잘 표현되고 있는것이 나타납니다.
그러나 strace 없이는 화면에 이 xml 자료가 나오지 않습니다
[pid 28735] fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 5), ...}) = 0 [pid 28735] write(1, "<!DOCTYPE node PUBLIC \"-//freede"..., 143<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> ) = 143 [pid 28735] write(1, "<node>\n", 7<node> ) = 7 [pid 28735] write(1, " <interface name=\"tld.example.F"..., 37 <interface name="tld.example.Foo"> ) = 37 [pid 28735] write(1, " <method name=\"method\">\n", 27 <method name="method"> ) = 27 [pid 28735] write(1, " <arg name=\"foo\" type=\"s\" d"..., 48 <arg name="foo" type="s" direction="in"/> ) = 48 [pid 28735] write(1, " </method>\n", 14 </method> ) = 14 [pid 28735] write(1, " </interface>\n", 15 </interface> ) = 15 [pid 28735] write(1, "</node>\n", 8</node> ) = 8
추측하기로 qt4.7.1 에 구현된 Qprocess 나 Qthread 에서 clone으로 생겨난 자식 프로세스를 제대로 처리 못하고 있는게 아닌가 의심됩니다
moc 에서 에러가 나는 경우라면 qmake 가
moc 에서 에러가 나는 경우라면 qmake 가 제대로 처리되지 않았을 확률이 높은데 이 부분은 체크해 보셨는지요.
4.7.1을 windows mobile 6.5 에 올려보았는데요
WEBKIT, XML, NETWORK 정상작동합니다만.. // 가끔 Qthread가 죽어버립니다.. 원인불명.. stack trace 가 안되네요 .ㅜ
음.. 절망적인건... 속도가 너무 구리네요..
그래서 그냥 php로 모든것을 해결하려 합니다. ㅜㅜ