<reactor>kqueue</reactor>
то, скорее всего pyicqt начнет кушать 100% CPU. Если посмотреть ktrace, то можно будет увидеть следующее:
25821 python2.5 RET kevent -1 errno 9 Bad file descriptor
25821 python2.5 CALL gettimeofday(0xbfbfd8c8,0)
25821 python2.5 RET gettimeofday 0
25821 python2.5 CALL gettimeofday(0xbfbfd5b8,0)
25821 python2.5 RET gettimeofday 0
25821 python2.5 CALL write(0x2,0x28e70014,0x2ab)
25821 python2.5 GIO fd 2 wrote 683 bytes
"Traceback (most recent call last):
File "/usr/local/lib/jabber/pyicq/PyICQt.py", line 16, in <module>
main.main()
File "/usr/local/lib/jabber/pyicq/src/main.py", line 473, in main
reactor.run()
File "/usr/local/lib/python2.5/site-packages/twisted/internet/base.py", line 1128, in run
self.mainLoop()
--- <exception caught here> ---
File "/usr/local/lib/python2.5/site-packages/twisted/internet/base.py", line 1140, in mainLoop
self.doIteration(t)
File "/usr/local/lib/python2.5/site-packages/twisted/internet/kqreactor.py", line 189, in doKEvent
l = self._kq.kevent([], len(self._selectables), timeout)
exceptions.OSError: [Errno 9] Bad file descriptor
"
Вспоминаем неприятную особенность kqueue: при форке не наследуюся kqueue дескрипторы. То есть, необходимо выполнить демонизацию самостоятельно. Вторая проблема - неверный расчет тайм-аутов. Фикс ее:
--- kqsyscallmodule.c.bak 2009-10-02 18:24:37.000000000 +0400
+++ kqsyscallmodule.c 2009-10-02 18:26:37.000000000 +0400
@@ -141,7 +141,7 @@
}
statichere PyTypeObject KQEvent_Type = {
- PyObject_HEAD_INIT(NULL)
+ PyObject_HEAD_INIT(&PyType_Type)
0, // ob_size
"KQEvent", // tp_name
sizeof(KQEventObject), // tp_basicsize
@@ -295,14 +295,14 @@
/* Build timespec for timeout */
totimespec.tv_sec = timeout / 1000;
- totimespec.tv_nsec = (timeout % 1000) * 100000;
+ totimespec.tv_nsec = (timeout % 1000) * 1000000;
// printf("timespec: sec=%d nsec=%d\n", totimespec.tv_sec, totimespec.tv_nsec);
/* Make the call */
-
+ Py_BEGIN_ALLOW_THREADS
gotNumEvents = kevent (self->fd, changelist, haveNumEvents, triggered, wantNumEvents, &totimespec);
-
+ Py_END_ALLOW_THREADS
/* Don't need the input event list anymore, so get rid of it */
free (changelist);
@@ -365,7 +365,7 @@
statichere PyTypeObject KQueue_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
- PyObject_HEAD_INIT(NULL)
+ PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"KQueue", /*tp_name*/
sizeof(KQueueObject), /*tp_basicsize*/
Очевидно, что для получения наносекунд, нужно умножить миллисекунды на миллион, а не на сто тысяч.
Вторая проблема - корявая демонизация. Я решил ее исправлением стартового скрипта следующим образом:
--- /usr/local/etc/rc.d/jabber-pyicq-transport.orig 2009-10-02 18:57:06.000000000 +0400
+++ /usr/local/etc/rc.d/jabber-pyicq-transport 2009-10-02 19:29:00.000000000 +0400
@@ -24,8 +24,9 @@
: ${jabber_pyicq_user="ejabberd"}
pidfile="${jabber_pyicq_piddir}/PyICQt.pid"
-command_interpreter="/usr/local/bin/python2.5"
-command="${jabber_pyicq_dir}/PyICQt.py"
-command_args="-b -o pid=${pidfile}"
+python="/usr/local/bin/python2.5"
+procname="${python}"
+command="/usr/sbin/daemon"
+command_args="${python} ${jabber_pyicq_dir}/PyICQt.py -o pid=${pidfile}"
run_rc_command "$1"
То есть, демонизация происходит при помощи /usr/sbin/daemon. Проверка трейса работы pyicqt показала, что после этих действий для работы он использует kevent, причем, использует правильно. Хотя наличие select'ов все равно смущает, но для socket IO он все же использует kqueue.
No comments:
Post a Comment