Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > WaitForSingleObject в созданном потоке


Автор: freezeman 25.3.2012, 10:23
Всем привет!

Подскажите, пожалуйста, в чем может быть проблема...
Создал в консоли событие и ожидаю ответ функцией WaitForSingleObject из другого приложения PulseEvent...все работает как задумано.

Но когда перенес код в службу в отдельный поток, вылетает после WaitForSingleObject...

Создавал поток в службе так:
Код

MyWaitForSingleObject() {
    ...
}

DWORD WINAPI ThreadFunc(LPVOID v) {
   MyWaitForSingleObject();
}

// Здесь стартует сервис
void CServiceContext::OnServiceStart()
{
   DWORD thID;
   DWORD PID = 1000;
   CreateThread(NULL, NUll, ThreadFunc, &PID, NULL, &thID);
}


И ещё, как удалить поток с помощью RemoteThread?

Автор: freezeman 25.3.2012, 12:12
Подскажите, please! Что только не перепробовал...проблема скорее всего в потоке, как решить??

Автор: volatile 25.3.2012, 12:53
Цитата(freezeman @  25.3.2012,  12:12 Найти цитируемый пост)
Подскажите, please! Что только не перепробовал...проблема скорее всего в потоке, как решить?? 

Чтоб получить ответ, нужно правильно сформировать вопрос.
В вашем коде нет вобще ничего.
где WaitForSingleObject  ?
что означает
Цитата(freezeman @  25.3.2012,  10:23 Найти цитируемый пост)
 вылетает после WaitForSingleObject...

вылетает с ошибкой, или что?

Автор: freezeman 25.3.2012, 13:01
Цитата(volatile @ 25.3.2012,  12:53)
Цитата(freezeman @  25.3.2012,  12:12 Найти цитируемый пост)
Подскажите, please! Что только не перепробовал...проблема скорее всего в потоке, как решить?? 

Чтоб получить ответ, нужно правильно сформировать вопрос.
В вашем коде нет вобще ничего.
где WaitForSingleObject  ?
что означает
Цитата(freezeman @  25.3.2012,  10:23 Найти цитируемый пост)
 вылетает после WaitForSingleObject...

вылетает с ошибкой, или что?

Я написал код создания потока, думаю там ошибка... Когда тот же код выполняю в основном потоке работает нормально, в созданном мною вылетает без ошибки

Код:
Код

// ServiceContext.cpp: implementation of the CServiceContext class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ServiceContext.h"
#include "ServiceHelper.h"
#include <fstream>
#include <stdlib.h>
#include <Windows.h>
#include <tlhelp32.h>
#include <malloc.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <tchar.h>
#include <psapi.h>
#include <strsafe.h>
#include <string.h>
using namespace std;

#define BUF_SIZE 512
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("Message from first process.");

int MyWaitSingleObject(void);

struct ReadFileParam
{
    HANDLE hFile;
    LPVOID lpBuffer;
    DWORD nNumberOfBytesToRead;
    LPDWORD lpNumberOfBytesRead;
    LPOVERLAPPED lpOverlapped;
};

int MyWaitSingleObject(void)
{
    FILE *out;
    out = fopen("c:\\service.txt", "at");
    fprintf(out, " | Сообщение из MyWaitSingleObject | \n");
    fclose(out);

    HANDLE hMapFile;
    ReadFileParam *pBuf;
    HANDLE hEvent = ::CreateEvent (NULL, true, false, TEXT("MyEvent\0")); //Открываем событие

    if (hEvent == NULL) {
        return 1;
    }

    hMapFile = CreateFileMapping(
                    INVALID_HANDLE_VALUE,    
                    NULL,                    
                    PAGE_READWRITE,          
                    0,                       
                    BUF_SIZE,                
                    szName);                 

    if (hMapFile == NULL)
    {
        return 1;
    }
    pBuf = (struct ReadFileParam*)MapViewOfFile(hMapFile,   
                                        FILE_MAP_ALL_ACCESS, 
                                        0,
                                        0,
                                        BUF_SIZE);
    if (pBuf == NULL)
    {
        FILE *out;
        out = fopen("c:\\service.txt", "at");
        fprintf(out, " | Error. Could not map view of file | \n");
        fclose(out);
        CloseHandle(hMapFile);
        return 1;
    }

    while (true) {
        WaitForSingleObject(hEvent, INFINITE); //Ждём появления данных для получения
    }
    UnmapViewOfFile(pBuf);

    CloseHandle(hMapFile);
    return 0;
}


DWORD WINAPI ThreadFunc2(LPVOID s1)
{
    FILE *out;
    out = fopen("c:\\service.txt", "at");
    fprintf(out, " | Сообщение из созданного потока ThreadFunc2| \n");
    fclose(out);
    MyWaitSingleObject();
   return 0;
}

HANDLE hThreadInject;
HANDLE hThreadStat;
void CServiceContext::OnServiceStart()
{
     FILE *out;
     out = fopen("c:\\service.txt", "at");
     fprintf(out, "Сервис запущен.\n");
     fclose(out);

     DWORD thID2;
     DWORD PID2 = 1000;
     hThreadStat = CreateThread(NULL, NULL, ThreadFunc2, &PID2, NULL, &thID2);

     DWORD thID;
     DWORD PID = 1000;
     hThreadInject = CreateThread(NULL, NULL, ThreadFunc, &PID, NULL, &thID);
}

void CServiceContext::OnServiceStop()
{
     FILE *out;
     out = fopen("c:\\service.txt", "at");
     fprintf(out, "Сервис остановлен.\n");
     CloseHandle(hThreadInject);
     fprintf(out, "Поток hThreadInject остановлен.\n");
     CloseHandle(hThreadStat);
     fprintf(out, "Поток hThreadStat остановлен.");
     fclose(out);
}



Добавлено через 11 минут и 59 секунд
Может какие-нибудь особенности есть?? Я только выяснил, что ни проекция созданная в памяти не открылась, ни событие CreateEvent...

Автор: volatile 25.3.2012, 14:12
Цитата(freezeman @  25.3.2012,  13:01 Найти цитируемый пост)
Я только выяснил, что ни проекция созданная в памяти не открылась, ни событие CreateEvent

Ну так с этого и надо начинать было. 
Посмотрите что  GetLastError () говорит после CreateEvent(), почему не открылось?

Автор: Dem_max 25.3.2012, 14:17
Этот  код просто пипец
Код

    while (true) {
        WaitForSingleObject(hEvent, INFINITE); //Ждём появления данных для получения
    }

Автор: freezeman 25.3.2012, 14:20
Цитата(Dem_max @ 25.3.2012,  14:17)
Этот  код просто пипец
Код

    while (true) {
        WaitForSingleObject(hEvent, INFINITE); //Ждём появления данных для получения
    }

))))) Почему? У меня внедряется dll в процессы и перехватывает сообщения, перехватив в этом цикле получать сообщения о поступивших данных для статистики и обратно ожидать новых данных, после WaitForSingleObject полученные данные будут заноситься в массив для статистики... Есть более не пипецное решение?)))

Автор: Dem_max 25.3.2012, 14:30
Если в этот код передастся управление то он будет работать вечно и этот поток ужи ничего не выполнит

Автор: freezeman 25.3.2012, 14:38
Цитата(Dem_max @ 25.3.2012,  14:30)
Если в этот код передастся управление то он будет работать вечно и этот поток ужи ничего не выполнит

Я думаю, что после создания проецируемого файла и события, зайдя в цикл требуется только принимать данные, которые записываются в проец. файл и посылается событие PulseEvent из другой программы, тем самым получается бесконечные "приёмник"...

Я ошибаюсь?

Автор: Dem_max 25.3.2012, 14:41
Ошибаешься, поток войдет в бесконечный цикл и больше ничего не сделает никогда, даже поток никогда не закроется корректно.

Автор: freezeman 25.3.2012, 14:50
Цитата(Dem_max @ 25.3.2012,  14:41)
Ошибаешься, поток войдет в бесконечный цикл и больше ничего не сделает никогда, даже поток никогда не закроется корректно.

Ну это не главная проблема... я тестировал вроде бы работало с одним сообщением это точно, с очередью не проверил, думал все нормально...

Подскажи, пожалуйста, почему когда я создаю проекцию и событие в основном потоке, то в других приложениях они благополучно открываются, а если выношу в отдельный поток, то нет...

Автор: Dem_max 25.3.2012, 14:58
ответы тут 
http://forum.vingrad.ru/index.php?showtopic=349158&view=findpost&p=2473241

Автор: freezeman 25.3.2012, 15:10
Цитата(volatile @ 25.3.2012,  14:12)
Цитата(freezeman @  25.3.2012,  13:01 Найти цитируемый пост)
Я только выяснил, что ни проекция созданная в памяти не открылась, ни событие CreateEvent

Ну так с этого и надо начинать было. 
Посмотрите что  GetLastError () говорит после CreateEvent(), почему не открылось?

Если я сделал все правильно, код ошибки 0x5

Автор: volatile 25.3.2012, 15:39
Цитата(freezeman @  25.3.2012,  15:10 Найти цитируемый пост)
Если я сделал все правильно, код ошибки 0x5 

Number: 5
Constant: ERROR_ACCESS_DENIED

Проблема в первом аргументе функции 
Цитата(freezeman @  25.3.2012,  13:01 Найти цитируемый пост)
CreateEvent (NULL, true, false, TEXT("MyEvent\0")); 

там должны быть нормальные аттрибуты, а не NULL

Верней даже не здесь, а в основной программе, которая и создает первый евент.

Автор: freezeman 25.3.2012, 15:43
Цитата(volatile @ 25.3.2012,  15:39)
Цитата(freezeman @  25.3.2012,  15:10 Найти цитируемый пост)
Если я сделал все правильно, код ошибки 0x5 

Number: 5
Constant: ERROR_ACCESS_DENIED

Проблема в первом аргументе функции 
Цитата(freezeman @  25.3.2012,  13:01 Найти цитируемый пост)
CreateEvent (NULL, true, false, TEXT("MyEvent\0")); 

там должны быть нормальные аттрибуты, а не NULL

Верней даже не здесь, а в основной программе, которая и создает первый евент.

Представляете, создал отдельный консольный проект создал там дочерний поток и все заработало, но мне нужно именно в моей службе реализовать... просто понятия не имею в чем проблема...

Как вы говорите о параметре в CreateEvent, почему же в другом проекте все заработало??

Автор: xvr 25.3.2012, 15:46
Цитата(freezeman @  25.3.2012,  14:20 Найти цитируемый пост)
 Есть более не пипецное решение?)))

Ваш цикл почти полностью аналогичен for(;;) ; (Отличие в том, что он не жрет процессор на 100% и сбрасывает event). Но в том, что он блокирует выполнение потока и никакие event'ы его отсюда не выведут, он аналогичен полностью.

Цитата(freezeman @  25.3.2012,  15:10 Найти цитируемый пост)
Если я сделал все правильно, код ошибки 0x5 

Это ACCESS_DENIED. Проблема не в том, что у вас отдельный поток, а в том, что у вас сервис. Окружение сервиса отличается от окружения пользовательского приложения. Попробуйте запустить свой сервис под вашим account'ом (а не под local system) - если заработает, то ищите недостающие права

Добавлено через 3 минуты и 21 секунду
Цитата(freezeman @  25.3.2012,  15:43 Найти цитируемый пост)
Как вы говорите о параметре в CreateEvent, почему же в другом проекте все заработало?? 

В правах. NULL в первом параметре - это права по умолчанию, а это значит, что права есть только у администратора и создателя объекта (т.е. local system для сервиса). Простой смертный пользователь этот объект открыть не сможет

Автор: volatile 25.3.2012, 15:52
freezeman, гуглите про SECURITY_ATTRIBUTES

Автор: freezeman 25.3.2012, 15:59
Цитата(xvr @ 25.3.2012,  15:46)
Цитата(freezeman @  25.3.2012,  14:20 Найти цитируемый пост)
 Есть более не пипецное решение?)))

Ваш цикл почти полностью аналогичен for(;;) ; (Отличие в том, что он не жрет процессор на 100% и сбрасывает event). Но в том, что он блокирует выполнение потока и никакие event'ы его отсюда не выведут, он аналогичен полностью.

Цитата(freezeman @  25.3.2012,  15:10 Найти цитируемый пост)
Если я сделал все правильно, код ошибки 0x5 

Это ACCESS_DENIED. Проблема не в том, что у вас отдельный поток, а в том, что у вас сервис. Окружение сервиса отличается от окружения пользовательского приложения. Попробуйте запустить свой сервис под вашим account'ом (а не под local system) - если заработает, то ищите недостающие права

Добавлено @ 15:49
Цитата(freezeman @  25.3.2012,  15:43 Найти цитируемый пост)
Как вы говорите о параметре в CreateEvent, почему же в другом проекте все заработало?? 

В правах. NULL в первом параметре - это права по умолчанию, а это значит, что права есть только у администратора и создателя объекта (т.е. local system для сервиса). Простой смертный пользователь этот объект открыть не сможет

Да что это такое с самого утра, с 10 утра я сидел и решал эту задачу!!!! Одного вашего сообщения хватило, все заработало!!! 
СПАСИБО БОЛЬШОЕ!!!

Автор: freezeman 25.3.2012, 16:33
Цитата(volatile @ 25.3.2012,  15:52)
freezeman, гуглите про SECURITY_ATTRIBUTES

Нашел описание, уже завтра разберусь... СПАСИБО БОЛЬШОЕ!!!

Автор: freezeman 25.3.2012, 20:19
Решил проблему с правами, добавив следующий SECURITY_ATTRIBUTES:
Код

    PSECURITY_DESCRIPTOR pSD; 
    SECURITY_ATTRIBUTES sa; 

    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
         SECURITY_DESCRIPTOR_MIN_LENGTH); 

    if (pSD == NULL)
      return 1; 

    if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
      return 1; 

    if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE))
       return 1;

    sa.nLength = sizeof(sa); 
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = TRUE; 



ЕЩЁ РАЗ ВСЕМ БОЛЬШОЕ СПАСИБО ЗА ПОМОЩЬ, C++ И WINAPI НАЧАЛ ТОЛЬКО ИЗУЧАТЬ (ЖИЗНЬ ЗАСТАВИЛА:), В .NET ПРИВЫК... 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)