mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 14:48:18 +02:00
* Fix access violation: module can be reset while loading dependent units. Fixes issue #40705
This commit is contained in:
parent
ee1916e919
commit
564597a573
@ -368,6 +368,9 @@ begin
|
||||
e:=ttask_list(Hash.Find(n));
|
||||
if e=nil then
|
||||
begin
|
||||
// Clear reset flag.
|
||||
// This can happen when during load, reset is done and unit is added to task list.
|
||||
m.is_reset:=false;
|
||||
t:=ttask_list.create(m);
|
||||
list.insert(t);
|
||||
hash.Add(n,t);
|
||||
@ -379,6 +382,7 @@ begin
|
||||
// We have a task, if it was reset, then clear the state and move the task to the start.
|
||||
if m.is_reset then
|
||||
begin
|
||||
{$IFDEF DEBUG_CTASK}Writeln(m.ToString,' was reset, resetting flag. State: ',m.state);{$ENDIF}
|
||||
m.is_reset:=false;
|
||||
t:=findtask(m);
|
||||
if assigned(t) then
|
||||
|
@ -2174,6 +2174,12 @@ var
|
||||
|
||||
procedure tppumodule.prepare_second_load(from_module: tmodule);
|
||||
|
||||
const
|
||||
CompileStates = [ms_compile, ms_compiling_waitintf, ms_compiling_waitimpl,
|
||||
ms_compiling_waitfinish, ms_compiling_wait, ms_compiled,
|
||||
ms_processed];
|
||||
|
||||
|
||||
begin
|
||||
{ try to load the unit a second time first }
|
||||
Message1(unit_u_second_load_unit,modulename^);
|
||||
@ -2182,7 +2188,7 @@ var
|
||||
flagdependent(from_module);
|
||||
{ Reset the module }
|
||||
reset;
|
||||
if state in [ms_compile] then
|
||||
if state in CompileStates then
|
||||
begin
|
||||
Message1(unit_u_second_compile_unit,modulename^);
|
||||
state:=ms_compile;
|
||||
@ -2253,7 +2259,6 @@ var
|
||||
flagdependent(from_module);
|
||||
{ Reset the module }
|
||||
reset;
|
||||
is_reset:=false;
|
||||
{ mark this module for recompilation }
|
||||
if not (state in [ms_compile]) then
|
||||
state:=ms_compile;
|
||||
|
@ -559,6 +559,7 @@ implementation
|
||||
filepos : tfileposinfo;
|
||||
isnew : boolean;
|
||||
|
||||
|
||||
begin
|
||||
consume(_USES);
|
||||
repeat
|
||||
@ -640,6 +641,7 @@ implementation
|
||||
state: tglobalstate;
|
||||
isLoaded : Boolean;
|
||||
mwait : tmodule;
|
||||
lu : tmodule;
|
||||
|
||||
procedure restorestate;
|
||||
|
||||
@ -650,7 +652,6 @@ implementation
|
||||
if assigned(current_scanner.inputfile) then
|
||||
current_scanner.tempopeninputfile;
|
||||
end;
|
||||
|
||||
state.free;
|
||||
end;
|
||||
|
||||
@ -663,35 +664,37 @@ implementation
|
||||
pu:=tused_unit(curr.used_units.first);
|
||||
while assigned(pu) do
|
||||
begin
|
||||
lu:=pu.u;
|
||||
{ Only load the units that are in the current
|
||||
(interface/implementation) uses clause }
|
||||
if pu.in_uses and
|
||||
(pu.in_interface=frominterface) then
|
||||
begin
|
||||
if (pu.u.state in [ms_processed, ms_compiled,ms_compiling_waitimpl]) then
|
||||
if (lu.state in [ms_processed, ms_compiled,ms_compiling_waitimpl]) then
|
||||
isLoaded:=true
|
||||
else if (pu.u.state=ms_registered) then
|
||||
else if (lu.state=ms_registered) then
|
||||
// try to load
|
||||
isLoaded:=tppumodule(pu.u).loadppu(curr)
|
||||
isLoaded:=tppumodule(lu).loadppu(curr)
|
||||
else
|
||||
isLoaded:=False;
|
||||
isLoaded:=IsLoaded and not pu.u.is_reset;
|
||||
isLoaded:=IsLoaded and not lu.is_reset ;
|
||||
if not IsLoaded then
|
||||
begin
|
||||
if mwait=nil then
|
||||
mwait:=pu.u;
|
||||
mwait:=lu;
|
||||
// In case of is_reset, the task handler will discard the state if the module was already there
|
||||
task_handler.addmodule(pu.u);
|
||||
task_handler.addmodule(lu);
|
||||
end;
|
||||
IsLoaded:=Isloaded and not curr.is_reset;
|
||||
Result:=Result and IsLoaded;
|
||||
{ If we were reset, then used_units is no longer correct, and we must exit at once. }
|
||||
if curr.is_reset then
|
||||
break;
|
||||
{ is our module compiled? then we can stop }
|
||||
if curr.state in [ms_compiled,ms_processed] then
|
||||
begin
|
||||
Restorestate;
|
||||
exit;
|
||||
end;
|
||||
break;
|
||||
{ add this unit to the dependencies }
|
||||
pu.u.adddependency(curr,frominterface);
|
||||
lu.adddependency(curr,frominterface);
|
||||
{ check hints }
|
||||
pu.check_hints;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user