Наконец отдебажил эту хуйню.
В общем, виноваты оказались, как всегда, арены.
Во-первых, я выделял вообще всё пространство арены целиком. Поэтому, когда размер объекта не кратен размеру арены, я выделял под последний элемент частично за пределами аллоцированной зоны. Первый проёб.
Во-вторых, arena_acquire(), чтобы получить указатель, где можно схоронить нужный объект, возвращал результат list_pop() из списка доступных поинтеров. Только вот, я не учёл, что list_pop() возвращает указатель на элемент внутри списка, а не сам элемент. То есть, в списке память хранится, как void*, а я в неё совал void*, так что по итогу память в списке имела тип void**. Вот как раз его и возвращал мне list_pop(). А я возвращал пользователю вместо указателя на свободное место в арене. Так ладно это, возвращал поинтеры с промежутком в 8 байт, равное как раз таки исходному
В общем, охуел я знатно, конечно. Зато теперь вынес ещё и закрытие сокета из ивентлупа в обёртку, что позволит ещё лучше всё это дело в io_uring потом батчить
В общем, виноваты оказались, как всегда, арены.
Во-первых, я выделял вообще всё пространство арены целиком. Поэтому, когда размер объекта не кратен размеру арены, я выделял под последний элемент частично за пределами аллоцированной зоны. Первый проёб.
Во-вторых, arena_acquire(), чтобы получить указатель, где можно схоронить нужный объект, возвращал результат list_pop() из списка доступных поинтеров. Только вот, я не учёл, что list_pop() возвращает указатель на элемент внутри списка, а не сам элемент. То есть, в списке память хранится, как void*, а я в неё совал void*, так что по итогу память в списке имела тип void**. Вот как раз его и возвращал мне list_pop(). А я возвращал пользователю вместо указателя на свободное место в арене. Так ладно это, возвращал поинтеры с промежутком в 8 байт, равное как раз таки исходному
sizeof(void*). Поэтому, у меня таски перекрывали друг дружку. Из-за этого мне поебенило состояние серверной таски. Таску с поебененным состоянием получал ивентлуп. Видит - хуйня какая-то, и логгирует баг. А логгер-то я не имплементировал, у меня там заглушка. Выходит, что я вызывал функцию по рандомному адресу в памяти. Отсюда и sigill. В общем, охуел я знатно, конечно. Зато теперь вынес ещё и закрытие сокета из ивентлупа в обёртку, что позволит ещё лучше всё это дело в io_uring потом батчить
Что делать
Photo
ТУПОЙ СЫН ГОВНА БЛЯТЬ
Когда клиент отключается, я добавляю таску в очередь на дисконнект, чтобы этим занялся враппер (дабы ивентлуп своими грязными ручками не прикасался к тому, что ему не принадлежит).
Соответственно, после этого я пытаюсь заменить таску на новую активную. Если не получается - просто инкрементируй значение inactives (чтобы потом по нему определить, пустая ли очередь активных ивентов, и тогда еполл встанет на ожидание до тех пор, пока новые не появятся)
И Я ЗАБЫЛ ОБОЗНАЧИТЬ САМУ ТАСКУ КАК НЕАКТИВНУЮ БЛЯЯЯЯЯЯЯЯЯТЬ
Из-за чего, соответственно, каждый раз, как я на неё натыкался - пытался из неё что-то прочитать. Каждый раз ловлю EOF. Каждый раз добавляю в очередь на дисконнект. И каждый раз обёртка пыталась её по второму, третьему, etc. кругу её освободить. Ёбаный пиздос
Когда клиент отключается, я добавляю таску в очередь на дисконнект, чтобы этим занялся враппер (дабы ивентлуп своими грязными ручками не прикасался к тому, что ему не принадлежит).
Соответственно, после этого я пытаюсь заменить таску на новую активную. Если не получается - просто инкрементируй значение inactives (чтобы потом по нему определить, пустая ли очередь активных ивентов, и тогда еполл встанет на ожидание до тех пор, пока новые не появятся)
И Я ЗАБЫЛ ОБОЗНАЧИТЬ САМУ ТАСКУ КАК НЕАКТИВНУЮ БЛЯЯЯЯЯЯЯЯЯТЬ
Из-за чего, соответственно, каждый раз, как я на неё натыкался - пытался из неё что-то прочитать. Каждый раз ловлю EOF. Каждый раз добавляю в очередь на дисконнект. И каждый раз обёртка пыталась её по второму, третьему, etc. кругу её освободить. Ёбаный пиздос
Что делать
How did they know?
Кстати долго ебался-ебался, пока не понял, что проблема состоит лишь в том, что у меня ивентлуп в какой-то момент, за отсутствием новых активных тасок, каким-то чудом снимает флаг неактивности с инактивной таски, которую я уже освободить успел
Перенёс очищение флага в обёртку, чтобы только при получении ивента из еполла его снимать, и всё зафурыкало. Правда, теперь он не выдерживает потока из тсп стресстестера
Перенёс очищение флага в обёртку, чтобы только при получении ивента из еполла его снимать, и всё зафурыкало. Правда, теперь он не выдерживает потока из тсп стресстестера
Что делать
Кстати долго ебался-ебался, пока не понял, что проблема состоит лишь в том, что у меня ивентлуп в какой-то момент, за отсутствием новых активных тасок, каким-то чудом снимает флаг неактивности с инактивной таски, которую я уже освободить успел Перенёс очищение…
А не выдерживает потому, что, оказывается, надо принимать подключения из серверного сокета до тех пор, пока EAGAIN не словишь. Иначе тебе больше никогда не придёт ивент, из-за чего accept-loop стопорится
Итак, у меня утечка памяти. Поставил принт и оказался прав - да, действительно, у меня просто какая-то из арен растёт по кд. Значит, где-то я не возвращаю указатели обратно.
Поскольку у меня куча разных арен под разные вещи, то нам придётся использовать advanced debugging technologies
По размеру типа гадать, какая именно арена раздувается
Поскольку у меня куча разных арен под разные вещи, то нам придётся использовать advanced debugging technologies
По размеру типа гадать, какая именно арена раздувается
Так, ну я расставил свои принты везде, где я вообще аллоцирую буфер для записи. Виновато 100% оно. Только вот есть проблема
Ни одна из вероятных точек не работает
Осталось только одно место - перед самим циклом диспатчинга ивентов. Но я всегда возвращаю тот буфер обратно при выходе из функции. Нихуя нипанятна
Ни одна из вероятных точек не работает
Осталось только одно место - перед самим циклом диспатчинга ивентов. Но я всегда возвращаю тот буфер обратно при выходе из функции. Нихуя нипанятна