Финализация threadvar под Linux

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Финализация threadvar под Linux

Сообщение VerLeon » 21.01.2020 08:05:45

Здравствуйте, уважаемые!

Просьба сразу не пинать ногами, в Free Pascal и Linux - новичок.
Есть dll под windows, написанная на FPC, она использует threadvar и чистит их автоматически при завершении треда с использованием Dll_Thread_Detach_Hook
Сама она потоками не управляет, так как это плагин (UDF для СУБД Firebird)
Есть задача перевести ее на Linux. Там, естественно никаких Dll_Thread_Detach_Hook нет, но есть TThreadManager.
Но видимо я неправильно себе представляю, как его прикрутить.
Код примерно такой (с большими сокращениями):

Код: Выделить всё
uses
  {$ifdef unix}cthreads,{$endif}
  SysUtils, Classes, MemTableList, IBLog;

procedure IniDllProc;
{$IFDEF WINDOWS}
procedure LibraryProcThreadDetach(Reason: LongInt);
{$ELSE}
procedure LibraryReleaseThreadVars;
{$ENDIF}

var
  {$IFDEF WINDOWS}
  oldProcThreadDetach: TDLL_Entry_Hook = nil;
  {$ELSE}
  oldReleaseThreadVars: TReleaseThreadVarsHandler = nil;
  {$ENDIF}

threadvar
  VarList: TStringList;
  TableList: TTableList;
  ListList: TStringList;

implementation 

procedure IniDllProc;
{$IFDEF UNIX}
var CurrentTM: TThreadManager;
{$ENDIF}
begin
  {$IFDEF WINDOWS}
  oldProcThreadDetach := Dll_Thread_Detach_Hook;
  Dll_Thread_Detach_Hook := @LibraryProcThreadDetach;
  {$ELSE}
  GetThreadManager(CurrentTM);
  oldReleaseThreadVars := CurrentTM.ReleaseThreadVars;
  CurrentTM.ReleaseThreadVars := @LibraryReleaseThreadVars;
  {$ENDIF}
end;

{$IFDEF WINDOWS}
procedure LibraryProcThreadDetach(Reason: LongInt);
begin
  Log('DLL_THREAD_DETACH');
  freeVarList;
  freeTableList;
  freeListList;
  if Assigned(oldProcThreadDetach) then oldProcThreadDetach(Reason);
end;
{$ELSE}
procedure LibraryReleaseThreadVars;
begin
  Log('ReleaseThreadVars');
  freeVarList;
  freeTableList;
  freeListList;
  if Assigned(oldReleaseThreadVars) then oldReleaseThreadVars;
end;
{$ENDIF}



При инициализации библиотеки вызывается код

Код: Выделить всё
begin
  IsMultiThread := True;
  IniDllProc;
end.


Процедуры freeVarList, freeTableList, freeListList как раз чистят threadvar'ы.
Под виндой все работает нормально - в логе появляется 'DLL_THREAD_DETACH', память освобождается, под линуксом в LibraryReleaseThreadVars не заходит судя по всему никогда (в логе ничего нет, память не освобождается)
Подскажите, как заставить это работать или какие еще есть способы под линуксом отловить завершение треда (при условии, что не мы его создаем и завершаем) и почистить его threadvar'ы?
VerLeon
незнакомец
 
Сообщения: 2
Зарегистрирован: 21.01.2020 06:54:00

Re: Финализация threadvar под Linux

Сообщение iskander » 22.01.2020 09:48:00

ThreadManager у библиотеки поди свой собственный и он не в курсе насчет чужих потоков.
А использование managed типов для threadvar не решит проблему?
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: Финализация threadvar под Linux

Сообщение VerLeon » 22.01.2020 11:51:57

iskander писал(а):ThreadManager у библиотеки поди свой собственный и он не в курсе насчет чужих потоков.
А использование managed типов для threadvar не решит проблему?


1. Ну вот насчет менеджера я и сомневаюсь - что он знает и не знает. Но потоки-то не чужие - в их контексте сама библиотека работает. Но менеджер у нее может быть свой и знать он может только про те потоки, которые эта библиотека сама породила - это да. Ну тогда остается общий вопрос - как в линуксе отловить завершение треда в библиотеке? Ведь FPC как-то оперирует threadvar'ами в библиотеке и понимает в каком потоке какие у них значения (и есть ли они вообще)
2. Имхо managed не поможет даже если переделать TStringList на dynamic array, потому что в этих TStringList в objects хранятся ссылки на другие TStringList, т.е. просто правильно уничтожить саму threadvar мало, надо еще правильно уничтожить все, что в нее динамически понапихано (что и делают процедуры freeVarList, freeTableList, freeListList).
VerLeon
незнакомец
 
Сообщения: 2
Зарегистрирован: 21.01.2020 06:54:00

Re: Финализация threadvar под Linux

Сообщение iskander » 26.01.2020 13:04:40

Есть ли какие-либо новости?

VerLeon писал(а):Но потоки-то не чужие - в их контексте сама библиотека работает.

"Чужие" это образное выражение, правильнее конечно их называть "внешние".
VerLeon писал(а): Имхо managed не поможет

Идея использовать managed переменные скорее всего бестолковая, в случае внешних потоков они также будут требовать ручной финализации.
VerLeon писал(а):FPC как-то оперирует threadvar'ами в библиотеке и понимает в каком потоке какие у них значения (и есть ли они вообще)

Если я правильно путаю:
FPC(компилятор) просто пишет в бинарник секцию threadvar и её размер. Линкер формирует thread local storage(TLS) и секция threadvar отображается на TLS. При загрузке бинарника TLS обнуляется. За то чтобы у каждого потока была своя копия TLS отвечает потоковая библиотека и/или ось.

А почему нельзя очищать память при выходе из экспортируемой функции?
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 25

Рейтинг@Mail.ru
cron