вторник, 1 марта 2011 г.

Повышаем стабильность запуска SeleniumRC по крону

В одном из предыдущих постов я описывал вариант использования SeleniumRC на Linux-машине с использованием cron и виртуального X-сервера Xvfb.

Некоторое время эта связка работала исправно. crond - обеспечивал то, что RC всегда запущен, сам RC прилежно "гонял" тесты. Но время от времени случались непонятные массовые провалы автотестов со следующими записями в STDERR:


10:23:50.037 INFO - Preparing Firefox profile...
Error: cannot open display: :1
10:24:16.152 ERROR - Failed to start new browser session, shutdown browser and clear all session data
java.lang.RuntimeException: Timed out waiting for profile to be created!
at org.openqa.selenium.server.browserlaunchers.FirefoxChromeLauncher.waitForFullProfileToBeCreated(FirefoxChromeLauncher.java:348)
....

После некоторого времени "копания" выяснил (по информации от syslog-а), что в Xvfb периодически случался SIGFAULT (причина пока не ясна и требует отдельного времени на анализ). Ну случался и случался - никто не мешает также по крону запускать и сам Xvfb. Да, только есть ньюанс. Эта утилита, как принято у *nix-демонов, при запуске создает лок-файл со своим pid-ом. Делается это для предотвращения попытки запуска нескольких виртуальных серверов на одном и том же виртуальном дисплее.

Все хорошо, только разработчики забыли сделать "джентльменскую" проверку "живости" того самого процесса, pid которого любезно указан в lock-файле. Соответственно, после аварийного завершения самогО процесса давно нет в живых, но его lock-файл все еще на диске и мешает запуску новых экземпляров Xvfb.

Рассуждая дальше, как говорится "нечего на зеркало пинять.." , ведь я при периодическом запуске Xvfb и RC не позаботился (подобно разработчикам самогО Xvfb) о проверке того, запустился ли виртуальный менеджер окон или нет , поэтому и получал запущенный SeleniumRC, не имеющий в своем распоряжении виртуального дисплея , где бы он мог корректно запустить Firefox. В итоге, простая проверка и принудительная чистка ненужных уже lock-ов позволили "закрыть" глаза на возможные ошибки в стороннем ПО, получая стабильный результат тестирования собственного.

"Мораль сей басни такова": если указываешь другим на их ошибки, старайся сам не допускать аналогичных =)

8 комментариев:

  1. Написал коментарий а он исчез :(
    Смысл - сделано так специально, т.к. Xvnc ведет себя аналогично. Думаю возможно из-за соображений безопасности: сервис на том же хосте запущен другим пользователем, запрет по xhosts или аналог nolisten у X-сервера.

    ОтветитьУдалить
  2. Я ничего не удалял =)
    Да, скорее всего действительно "так и задумано". И внешняя проверка живости и удаление ненужного lock-файла позволяют запустить новый экземпляр, что мне и нужно)

    ОтветитьУдалить
  3. Да, я знаю, что Вы ничего не удаляли :), т.к. комент исчез сразу после публикации. Т.е. он не появился если говорить точнее.

    А проверка живости осуществляется по таймауту? Я для vnc не стал с этим заморачиваться - просто убиваю существующий, очищаю локи (их там два вроде) и запускаю новый.

    ОтветитьУдалить
  4. По ходу дела выяснил еще одну неявную проблемку ) Допустим , что Xvfb аварийно завершился, оставив pid в lock-файле. Спустя некоторое время мы анализируем этот lock, проверяя есть ли такой процесс в системе. При этом есть вероятность, что мы найдем такой процесс - планировщик может отдать этот pid совершенно другому приложению, запущенному от имени совершенно другого пользователя. Поэтому , либо проверять еще допонительно, а что именно за процесс под нашим pid-ом. Либо сильно себе все упростить:
    1. принудительно завершить все имеющиеся Xvfb у текущего пользователя
    2. почистить локи (на случай если все-таки было аварийное завершение)
    3. запустить свежий Xvfb

    И так каждый раз (силами crond) перед началом очередного сеанса автоматического тестирования)

    :)

    ОтветитьУдалить
  5. в тему о cron и повторных запусках процесса - есть статья на хабре с последующим отсылом на flock.

    ОтветитьУдалить
  6. Или еще проще:

    if ! pgrep -u admin Xvfb; then rm -f /tmp/X1-lock; Xvfb :1; fi

    ОтветитьУдалить
  7. Xvfb все еще падает с завидной постоянностью. Удалось подсечь его сообщение в /var/log/messages

    Mar 18 04:52:16 xen2 kernel: Xvfb[32394]: segfault at ffffffff00000028 rip 0000003d31270769 rsp 00007fff795fb610 error 6

    Корки не генерируются. Добавлю ulimit -c unlimited перед запуском xvfb , дождусь корку и тогда станет яснее , почему утилита падает.

    ОтветитьУдалить
  8. Вот стек на момент падения Xvfb:

    GDB was configured as "x86_64-redhat-linux-gnu".
    For bug reporting instructions, please see:
    ...
    Reading symbols from /usr/bin/Xvfb...(no debugging symbols found)...done.
    Reading symbols from /usr/lib64/libXfont.so.1...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib64/libXfont.so.1
    Reading symbols from /usr/lib64/libXau.so.6...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib64/libXau.so.6
    Reading symbols from /usr/lib64/libfontenc.so.1...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib64/libfontenc.so.1
    Reading symbols from /usr/lib64/libXdmcp.so.6...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib64/libXdmcp.so.6
    Reading symbols from /lib64/libpam_misc.so.0...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libpam_misc.so.0
    Reading symbols from /lib64/libpam.so.0...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libpam.so.0
    Reading symbols from /lib64/libselinux.so.1...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libselinux.so.1
    Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libm.so.6
    Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libc.so.6
    Reading symbols from /usr/lib64/libfreetype.so.6...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib64/libfreetype.so.6
    Reading symbols from /usr/lib64/libz.so.1...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib64/libz.so.1
    Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libdl.so.2
    Reading symbols from /lib64/libaudit.so.0...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libaudit.so.0
    Reading symbols from /lib64/libsepol.so.1...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libsepol.so.1
    Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
    Loaded symbols for /lib64/ld-linux-x86-64.so.2
    Reading symbols from /lib64/libnss_files.so.2...(no debugging symbols found)...done.
    Loaded symbols for /lib64/libnss_files.so.2
    Core was generated by `Xvfb :1'.
    Program terminated with signal 11, Segmentation fault.
    #0 0x0000003d31270769 in malloc_consolidate () from /lib64/libc.so.6
    (gdb) bt
    #0 0x0000003d31270769 in malloc_consolidate () from /lib64/libc.so.6
    #1 0x0000003d3127224c in _int_free () from /lib64/libc.so.6
    #2 0x0000003d3127276b in free () from /lib64/libc.so.6
    #3 0x00000000006a4542 in miCloseIndexed ()
    #4 0x000000000069b4ad in PictureCloseScreen ()
    #5 0x00000000004a266f in ?? ()
    #6 0x00000000006a2b3e in ?? ()
    #7 0x0000000000440bee in ?? ()
    #8 0x0000003d3121d994 in __libc_start_main () from /lib64/libc.so.6
    #9 0x000000000041e909 in getservbyname ()
    #10 0x00007fff119e67a8 in ?? ()
    #11 0x0000000000000000 in ?? ()

    ОтветитьУдалить