The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
fastcgi в нескольких потоках, !*! scx75, 14-Мрт-12, 12:27  [смотреть все]
Здравствуйте.
Пишу прогу на си++. Пытаюсь обработать fastcgi запрос в нескольких потоках, принимая только одним
код примерно следующий:

while(FCGX_Accept_r(&req)==0) {
  // кладу в общую очередь объект req
  FCGX_Init_req(&req); // точно не помню названия функции
  // семафор.post();
}

в потоках делаю следующее:


while(true) {
  семафор.wait();
  // req = вынимаю из очереди
  // обрабатываю, вывожу ответ
  FCGX_Finish_r(&req); // объекты req локальные в каждом из потоков
}

тестирую совместо с nginx, и поведение неоднозначно, в основном nginx выдает 502, бывает падает с ошибками памяти
пробывал разные варианты, когда потоки "засыпали"
сейчас меня больше интересует, сможет ли меня кто нибудь проконсультировать, потому что не нашел обсуждений fastcgi на си

  • fastcgi в нескольких потоках, !*! parad, 13:46 , 14-Мрт-12 (1)
    лучше бы код привел, а не на память как-то так. зае*бись вопросы пошли.

    напрашиваются 3 ошибки( в порядке вероятности ):

    - кладешь в очеред, непроинициализированная FCGX_InitRequest'ом структура копируется, потом ты инициализируешь стековую переменную, а в очереди остается фигня. Тобишь измени порядок вызова FCGX_InitRequest и покладки в очередь.

    - фцги у тебя работает через std{in,out,err} - должен в многопоточном приложении по сокетам.

    - конкурентный доступ без блокировки к очереди в многопоточном приложении.

    учись задавать полные вопросы с описанием.

    • fastcgi в нескольких потоках, !*! scx75, 11:10 , 15-Мрт-12 (4)
      > - кладешь в очеред, непроинициализированная FCGX_InitRequest'ом структура копируется,
      > потом ты инициализируешь стековую переменную, а в очереди остается фигня. Тобишь
      > измени порядок вызова FCGX_InitRequest и покладки в очередь.

      инициализация есть
      полный код http://govnokod.com/6123

      > - фцги у тебя работает через std{in,out,err} - должен в многопоточном приложении
      > по сокетам.

      можно конкретнее?
      я пробывал вариант где while(FCGX_Request_r(&req) == 0) у каждого потока свой, тогда все отлично работает, но такой вариант не катит

      > - конкурентный доступ без блокировки к очереди в многопоточном приложении.

      это все есть, в коде только не привел

      • fastcgi в нескольких потоках, !*! parad, 16:26 , 15-Мрт-12 (6)
        ну теперь понятней. )

        у тебя:

        while(FCGX_Accept_r(&req) == 0)
        {
          ...
          handler_pool_.put_request(req);
          ...
        }

        А вот код из libfcgi:

        int FCGX_Accept_r(FCGX_Request *reqDataPtr)
        {
          FCGX_Finish_r(reqDataPtr);
          ...
        }

        где FCGX_Finish_r() все чистит, закрывает и освобождает память. тобишь поток не успевает ответить, а дескрипторы закрываются, память освобождается.

        нужно дописать строчку:

        while(FCGX_Accept_r(&req) == 0)
        {
          ...
          handler_pool_.put_request(req);
          FCGX_InitRequest( req, ... );  // < по коду фцги - не занимается освобождением ресурсов, такчто подайдет.
          ...
        }

  • fastcgi в нескольких потоках, !*! parad, 13:52 , 14-Мрт-12 (2)
    пс. почему топик в базах данных и sql?
  • fastcgi в нескольких потоках, !*! scx75, 14:42 , 15-Мрт-12 (5)
    вообщем то виновато что происходит это в следующем порядке:

    while(FCGX_Accept_r(&req) == 0)
    {    
        req2 = req1;
        FCGX_InitRequest(&req, listen_socket, 0); // переинициализируем чтобы при FCGX_Accept_r не очистились стримы
        std::string str = "Content-Type: text/html;\r\n\r\nasads";
        FCGX_PutStr(str.c_str(), str.size(), req2.out);
        FCGX_Finish_r(&req2);
    }

    • fastcgi в нескольких потоках, !*! parad, 16:28 , 15-Мрт-12 (7)
      • fastcgi в нескольких потоках, !*! scx75, 16:57 , 15-Мрт-12 (8)
        > верно.

        ну да, до этого додумался, а в чем дальше трабл непонятно
        в FCGX_InitRequest обнуляется память структуры и устанавливаются некоторые значения, но nginx почему то перестает принимает ответ от моей проги - выдает браузеру 502
        как при memset'е может затронуться содержимое указателей?

    • fastcgi в нескольких потоках, !*! scx75, 16:58 , 15-Мрт-12 (9)
      поправка:

      while(FCGX_Accept_r(&req) == 0)
      {    
          req2 = req;

      • fastcgi в нескольких потоках, !*! parad, 20:06 , 15-Мрт-12 (10) –1
        Поэксперементировал.

        Натолкнуло на мысль что разработчики fastcgi пи**расы. Полез в код и понял что разбираюсь в людях:

        Accept_r(reqDataPtr) дергает NewReader(reqDataPtr, ...) для создания потока in, NewReader(reqDataPtr, ...) дергает NewStream(reqDataPtr, ...), который содержит вот такие строчки:

        --------------
        ...
        FCGX_Stream_Data *data = (FCGX_Stream_Data *)Malloc(sizeof(FCGX_Stream_Data));
        data->reqDataPtr = reqDataPtr; // Указатель на себя прикапывают. :)
        ...
        --------------

        Тобишь паттерт поставщика-потребители в твоей реализации не прокатит. Нельзя реквест трогать, пока не отработает.

        Вот такой суперкастыль популярен в мире. )) Хоть сам реализовывай.

        • fastcgi в нескольких потоках, !*! scx75, 22:36 , 15-Мрт-12 (11)
          удивляюсь, как вам не жалко времени на один из 100500 вопросов, спасибо) сейчас попробую понять что написали
          • fastcgi в нескольких потоках, !*! parad, 12:03 , 16-Мрт-12 (13)
            дело 10мин. сейчас на проекте где предстоит реализовывать компонент над фцги. уже проводил исследовательскую работу на подготовительном этапе - смотрел, пробывал, но в глубь не лазял. отвечая на этот вопрос сам опыту набрался, который скоро пригодится, тк тоже бы первым делом писал один поток-поставщик и пул потоков потребителей. и как следствие словил бы ту-же граблю. такчто незачто. )
        • fastcgi в нескольких потоках, !*! scx75, 11:57 , 16-Мрт-12 (12)
          и все же не догнал, почему это влияет на результат?
          там же новые стримы делаются, на стримы req2 никак не должны влиять, не?
          • fastcgi в нескольких потоках, !*! parad, 12:06 , 16-Мрт-12 (14)
            строчка: FCGX_Accept_r(&req) - вот этот указатель прикапывается внутрях. даже если мы req скопируем куда-либо и занулим его память, внутрях будет использована эта переменная.
            • fastcgi в нескольких потоках, !*! scx75, 14:45 , 16-Мрт-12 (15)
              это то понятно, но нам не важна сама переменная, указатели на потоки то скопировали в другую, куда и производится вывод

              req2 = req;
              FCGX_InitRequest(&req, listen_socket, 0); // почистили req
              FCGX_PutStr(str.c_str(), str.size(), req2.out); // выводим в req2, где указатели потоков сохранились и не очищались




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру