mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-07 07:26:13 +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));
|
e:=ttask_list(Hash.Find(n));
|
||||||
if e=nil then
|
if e=nil then
|
||||||
begin
|
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);
|
t:=ttask_list.create(m);
|
||||||
list.insert(t);
|
list.insert(t);
|
||||||
hash.Add(n,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.
|
// We have a task, if it was reset, then clear the state and move the task to the start.
|
||||||
if m.is_reset then
|
if m.is_reset then
|
||||||
begin
|
begin
|
||||||
|
{$IFDEF DEBUG_CTASK}Writeln(m.ToString,' was reset, resetting flag. State: ',m.state);{$ENDIF}
|
||||||
m.is_reset:=false;
|
m.is_reset:=false;
|
||||||
t:=findtask(m);
|
t:=findtask(m);
|
||||||
if assigned(t) then
|
if assigned(t) then
|
||||||
|
@ -2174,6 +2174,12 @@ var
|
|||||||
|
|
||||||
procedure tppumodule.prepare_second_load(from_module: tmodule);
|
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
|
begin
|
||||||
{ try to load the unit a second time first }
|
{ try to load the unit a second time first }
|
||||||
Message1(unit_u_second_load_unit,modulename^);
|
Message1(unit_u_second_load_unit,modulename^);
|
||||||
@ -2182,7 +2188,7 @@ var
|
|||||||
flagdependent(from_module);
|
flagdependent(from_module);
|
||||||
{ Reset the module }
|
{ Reset the module }
|
||||||
reset;
|
reset;
|
||||||
if state in [ms_compile] then
|
if state in CompileStates then
|
||||||
begin
|
begin
|
||||||
Message1(unit_u_second_compile_unit,modulename^);
|
Message1(unit_u_second_compile_unit,modulename^);
|
||||||
state:=ms_compile;
|
state:=ms_compile;
|
||||||
@ -2253,7 +2259,6 @@ var
|
|||||||
flagdependent(from_module);
|
flagdependent(from_module);
|
||||||
{ Reset the module }
|
{ Reset the module }
|
||||||
reset;
|
reset;
|
||||||
is_reset:=false;
|
|
||||||
{ mark this module for recompilation }
|
{ mark this module for recompilation }
|
||||||
if not (state in [ms_compile]) then
|
if not (state in [ms_compile]) then
|
||||||
state:=ms_compile;
|
state:=ms_compile;
|
||||||
|
@ -559,6 +559,7 @@ implementation
|
|||||||
filepos : tfileposinfo;
|
filepos : tfileposinfo;
|
||||||
isnew : boolean;
|
isnew : boolean;
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
consume(_USES);
|
consume(_USES);
|
||||||
repeat
|
repeat
|
||||||
@ -640,6 +641,7 @@ implementation
|
|||||||
state: tglobalstate;
|
state: tglobalstate;
|
||||||
isLoaded : Boolean;
|
isLoaded : Boolean;
|
||||||
mwait : tmodule;
|
mwait : tmodule;
|
||||||
|
lu : tmodule;
|
||||||
|
|
||||||
procedure restorestate;
|
procedure restorestate;
|
||||||
|
|
||||||
@ -650,7 +652,6 @@ implementation
|
|||||||
if assigned(current_scanner.inputfile) then
|
if assigned(current_scanner.inputfile) then
|
||||||
current_scanner.tempopeninputfile;
|
current_scanner.tempopeninputfile;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
state.free;
|
state.free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -663,35 +664,37 @@ implementation
|
|||||||
pu:=tused_unit(curr.used_units.first);
|
pu:=tused_unit(curr.used_units.first);
|
||||||
while assigned(pu) do
|
while assigned(pu) do
|
||||||
begin
|
begin
|
||||||
|
lu:=pu.u;
|
||||||
{ Only load the units that are in the current
|
{ Only load the units that are in the current
|
||||||
(interface/implementation) uses clause }
|
(interface/implementation) uses clause }
|
||||||
if pu.in_uses and
|
if pu.in_uses and
|
||||||
(pu.in_interface=frominterface) then
|
(pu.in_interface=frominterface) then
|
||||||
begin
|
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
|
isLoaded:=true
|
||||||
else if (pu.u.state=ms_registered) then
|
else if (lu.state=ms_registered) then
|
||||||
// try to load
|
// try to load
|
||||||
isLoaded:=tppumodule(pu.u).loadppu(curr)
|
isLoaded:=tppumodule(lu).loadppu(curr)
|
||||||
else
|
else
|
||||||
isLoaded:=False;
|
isLoaded:=False;
|
||||||
isLoaded:=IsLoaded and not pu.u.is_reset;
|
isLoaded:=IsLoaded and not lu.is_reset ;
|
||||||
if not IsLoaded then
|
if not IsLoaded then
|
||||||
begin
|
begin
|
||||||
if mwait=nil then
|
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
|
// 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;
|
end;
|
||||||
|
IsLoaded:=Isloaded and not curr.is_reset;
|
||||||
Result:=Result and IsLoaded;
|
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 }
|
{ is our module compiled? then we can stop }
|
||||||
if curr.state in [ms_compiled,ms_processed] then
|
if curr.state in [ms_compiled,ms_processed] then
|
||||||
begin
|
break;
|
||||||
Restorestate;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
{ add this unit to the dependencies }
|
{ add this unit to the dependencies }
|
||||||
pu.u.adddependency(curr,frominterface);
|
lu.adddependency(curr,frominterface);
|
||||||
{ check hints }
|
{ check hints }
|
||||||
pu.check_hints;
|
pu.check_hints;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user