Ошибка при вызове EnterCriticalSection

Тема в разделе "WASM.WIN32", создана пользователем LordBublicXIII, 25 июн 2008.

  1. LordBublicXIII

    LordBublicXIII Андрей

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    10
    Задача: есть поток1 и поток2, которые работают по следующей схеме:
    ...есть переменная Ready=0
    ...поток1 стартует поток2 и засыпает пока Ready не будет 1
    ...поток2 нормально работает, инициализирует некоторую крит. секцию, после инициализации делает Ready=1
    ...поток2 крутится в вечном цикле, каждая итерация которого обёрнута в EnterCriticalSection+LeaveCriticalSection
    ...вдруг поток1 просыпается (т.к Ready=1) и вызывает свою процедуру, обёрнутую в EnterCriticalSection+LeaveCriticalSection с той же к/с, что и поток2
    ...поток2 на очередном витке цикла пытается сделать EnterCriticalSection и умирает (этого быть не должно).

    Описание ошибки: Access Violation: Write on Address 00000000. GetLastError и try+except не работают, т.к. Винда СРАЗУ ЖЕ убивает приложение без вопросов.

    Попытался логировать события (записывал содержимое структуры RTL_CRITICAL_SECTION):
    Код (Text):
    1. 9:19:29 ... before enter: DebugInfo = 14C250 LockCount = -1 RecursionCount = 0 OwningThread = 0 LockSemaphore = 0 Reserved = 0
    2. 9:19:29 ... after enter : DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 0 Reserved = 0
    3. 9:19:29 ... before leave: DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 0 Reserved = 0
    4. 9:19:29 ... after leave : DebugInfo = 14C250 LockCount = -1 RecursionCount = 0 OwningThread = 0 LockSemaphore = 0 Reserved = 0
    5. 9:19:29 ... before enter: DebugInfo = 14C250 LockCount = -1 RecursionCount = 0 OwningThread = 0 LockSemaphore = 0 Reserved = 0
    6. 9:19:29 ... after enter : DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 0 Reserved = 0
    7. 9:19:29 ... before leave: DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 0 Reserved = 0
    8. 9:19:29 ... after leave : DebugInfo = 14C250 LockCount = -1 RecursionCount = 0 OwningThread = 0 LockSemaphore = 0 Reserved = 0
    9. 9:19:29 ... before enter: DebugInfo = 14C250 LockCount = -1 RecursionCount = 0 OwningThread = 0 LockSemaphore = 0 Reserved = 0
    10. 9:19:29 ... after enter : DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 0 Reserved = 0
    11. 9:19:29 ... before leave: DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 0 Reserved = 0
    12. 9:19:29 ... after leave : DebugInfo = 14C250 LockCount = -1 RecursionCount = 0 OwningThread = 0 LockSemaphore = 0 Reserved = 0
    13. 9:19:29 ... before enter: DebugInfo = 14C250 LockCount = -1 RecursionCount = 0 OwningThread = 0 LockSemaphore = 0 Reserved = 0
    14. 9:19:29 ... after enter : DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 0 Reserved = 0
    15. 9:19:29 ... before enter: DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 0 Reserved = 0
    16. 9:19:29 ... before leave: DebugInfo = 14C250 LockCount = 1 RecursionCount = 1 OwningThread = 5A4 LockSemaphore = 764 Reserved = 0
    17. 9:19:29 ... after enter : DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = AA0 LockSemaphore = 764 Reserved = 0
    18. 9:19:29 ... after leave : DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = AA0 LockSemaphore = 764 Reserved = 0
    19. 9:19:29 ... before enter: DebugInfo = 14C250 LockCount = 0 RecursionCount = 1 OwningThread = AA0 LockSemaphore = 764 Reserved = 0
    (before enter и after enter - вызываются соответственно перед и после EnterCriticalSection, before leave и after leave - аналогично для LeaveCriticalSection).
    Видно, что поток1 ещё не вышел из к/с, как в неё попытался зайти поток2. before enter поток2 вызвал, а вот after enter - уже нет (приложение завершилось).

    Вопрос1: почему поток2 вместо ожидания умирает?
    Вопрос2: чем это лечится?
     
  2. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Код?
     
  3. LordBublicXIII

    LordBublicXIII Андрей

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    10
    Мало поможет, т.к.:
    1) Delphi
    2) кода много

    В общем можно смотреть схему работы и лог в посте №#1. Ответы на основные возможные вопросы:
    ...InitializeCriticalSection делаю 1 раз (на старте 2го потока, первый в это время спит).
    ...Все вызовы EnterCriticalSection и LeaveCriticalSection парные - пока 1ый поток не войдёт в к/с, всё просто супер.
    ...Оба потока в одном процессе =).
    ...Ни один из потоков не может войти в к/с 2 раза подряд.
    ...Других синхронизирующих примитивов / общих переменных у них нет.

    З.Ы.: если что - смотрите исходники, но я думаю, что это не метод...
     
  4. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    LordBublicXIII
    Скорее всего умирает основной поток, поскольку в dpr нет try\except (что весьма странно, т.к. в вызываемых функциях LoadResource и Resources[0]=GetRes предусмотрена генерация исключений). Копаться в этой "корявой путаннице" лень, но похоже у тебя просто Path не инициализирована - вот на LoadResource или Resources[0] и валится
    PS: нафига выносить инициализацию в отд.модуль, чтобы потом забыть ее вызвать ?! ;)
     
  5. LordBublicXIII

    LordBublicXIII Андрей

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    10
    leo,
    спасибо что дал мне пинка под зад! Я нашёл косяк - в LoadResource вместо
    Код (Text):
    1. if l < idx then
    надо было поставить
    Код (Text):
    1. if l <= idx then
    (иначе при первом же обращении получается выход за границы массива). Вся фишка была в том, что Delphi при отладке многопоточного приложения многократно кидала меня из потока в поток, а ошибка вылетела не в том потоке, который реально вызвал ошибку, а в том, который в этот момент пытался в лезть в крит. секцию.

    Прошу прощения, господа, что отнял ваше драгоценное время по своей тупости. Если модерам не сложно, тему можно удалить ФПЕНЬ!
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    LordBublicXIII
    Не поленился пройтись отладчиком. Так и есть - элементарная ошибка в LoadResource:
    Код (Text):
    1.   l := Length(ResList);
    2.   if l < idx then //!!! должно быть <=, иначе ResList = Nil и кранты :)
    PS: Прежде чем строить хитроумные версии, нужно элементарно пройтись отладчиком и посмотреть где валится...

    PS: Эх, не успел...
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    LordBublicXIII
    В сообщении об ошибке указывается ее адрес - запускаешь прогу заново, переходишь по этому адресу и смотришь в чем м.б. дело