From 7ff9d877a898147457e2f727053f52e64c19cd24 Mon Sep 17 00:00:00 2001 From: turleypol Date: Sun, 31 May 2026 11:45:35 +0200 Subject: [PATCH] Funcrefs do not detect pid change (#889) * test for sending a function to the same program * store executor pid inside funcrefs and classes * docs --- .../docs.polserver.com/pol100/corechanges.xml | 7 ++++- pol-core/bscript/bclassinstance.cpp | 10 +++--- pol-core/bscript/bclassinstance.h | 5 +-- pol-core/bscript/bobject.h | 7 +++-- pol-core/bscript/executor.cpp | 13 ++++---- pol-core/bscript/executor.h | 2 ++ pol-core/bscript/object.cpp | 12 +++++-- pol-core/doc/core-changes.txt | 2 ++ pol-core/pol/uoexec.h | 2 +- .../pol/testpkgs/funcref/send_same_prog.src | 31 +++++++++++++++++++ testsuite/pol/testpkgs/funcref/test_call.src | 5 +++ 11 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 testsuite/pol/testpkgs/funcref/send_same_prog.src diff --git a/docs/docs.polserver.com/pol100/corechanges.xml b/docs/docs.polserver.com/pol100/corechanges.xml index 9caa50f98..2357ff457 100644 --- a/docs/docs.polserver.com/pol100/corechanges.xml +++ b/docs/docs.polserver.com/pol100/corechanges.xml @@ -2,9 +2,14 @@
Latest Core Changes - 05-25-2026 + 05-31-2026
+ + 05-31-2026 + Turley: + When sending classes/functionobjects to the same script but different instance the wrong globals where used + 05-25-2026 Turley: diff --git a/pol-core/bscript/bclassinstance.cpp b/pol-core/bscript/bclassinstance.cpp index 27644d2a0..860a521f7 100644 --- a/pol-core/bscript/bclassinstance.cpp +++ b/pol-core/bscript/bclassinstance.cpp @@ -11,10 +11,11 @@ namespace Pol::Bscript { BClassInstance::BClassInstance( ref_ptr program, int index, - std::weak_ptr globals ) + std::weak_ptr globals, unsigned int pid ) : BStruct( OTClassInstance ), prog_( std::move( program ) ), index_( index ), + pid_( pid ), globals( std::move( globals ) ) { passert( index_ < prog_->class_descriptors.size() ); @@ -24,13 +25,14 @@ BClassInstance::BClassInstance( const BClassInstance& B ) : BStruct( B, OTClassI { prog_ = B.prog_; index_ = B.index_; + pid_ = B.pid_; globals = B.globals; } size_t BClassInstance::sizeEstimate() const { return base::sizeEstimate() + Clib::memsize( constructors_called ) + - sizeof( ref_ptr ) + sizeof( unsigned int ) + + sizeof( ref_ptr ) + 2 * sizeof( unsigned int ) + sizeof( std::weak_ptr ); } @@ -61,7 +63,7 @@ BFunctionRef* BClassInstance::makeMethod( const char* method_name ) if ( method_itr == methods.end() ) return nullptr; - return new BFunctionRef( prog_, method_itr->second.function_reference_index, globals, + return new BFunctionRef( prog_, pid_, method_itr->second.function_reference_index, globals, ValueStackCont{} ); } @@ -184,7 +186,7 @@ BObjectRef BClassInstance::get_member_id( const int id ) const auto funcref_index = prog_->class_descriptors.at( index_ ).constructor_function_reference_index; - return BObjectRef( new BFunctionRef( prog_, funcref_index, globals, ValueStackCont{} ) ); + return BObjectRef( new BFunctionRef( prog_, pid_, funcref_index, globals, ValueStackCont{} ) ); } return base::get_member_id( id ); diff --git a/pol-core/bscript/bclassinstance.h b/pol-core/bscript/bclassinstance.h index 45a1fabe8..db936fdb1 100644 --- a/pol-core/bscript/bclassinstance.h +++ b/pol-core/bscript/bclassinstance.h @@ -14,8 +14,8 @@ class BClassInstance final : public BStruct using base = BStruct; public: - BClassInstance( ref_ptr program, int index, - std::weak_ptr globals ); + BClassInstance( ref_ptr program, int index, std::weak_ptr globals, + unsigned int pid ); BClassInstance( const BClassInstance& B ); ~BClassInstance() override = default; @@ -46,6 +46,7 @@ public: // Class Machinery private: ref_ptr prog_; unsigned int index_; + unsigned int pid_; public: std::weak_ptr globals; diff --git a/pol-core/bscript/bobject.h b/pol-core/bscript/bobject.h index f8d4e8764..8132f84c2 100644 --- a/pol-core/bscript/bobject.h +++ b/pol-core/bscript/bobject.h @@ -930,8 +930,9 @@ class BFunctionRef final : public BObjectImp using base = BObjectImp; public: - BFunctionRef( ref_ptr program, unsigned function_reference_index, - std::weak_ptr globals, ValueStackCont&& captures ); + BFunctionRef( ref_ptr program, unsigned int pid, + unsigned function_reference_index, std::weak_ptr globals, + ValueStackCont&& captures ); BFunctionRef( const BFunctionRef& B ); private: @@ -945,6 +946,7 @@ public: unsigned pc() const; bool variadic() const; ref_ptr prog() const; + unsigned int pid() const; unsigned class_index() const; bool constructor() const; bool class_method() const; @@ -969,6 +971,7 @@ private: // Need to reference the program, not the Executor, as the exec that created // this funcref could be destroyed by the time the funcref gets called ref_ptr prog_; + unsigned int original_pid_; unsigned function_reference_index_; public: diff --git a/pol-core/bscript/executor.cpp b/pol-core/bscript/executor.cpp index 1452f62e8..9be4d3123 100644 --- a/pol-core/bscript/executor.cpp +++ b/pol-core/bscript/executor.cpp @@ -2726,8 +2726,8 @@ void Executor::ins_call_method_id( const Instruction& ins ) if ( funcr->constructor() ) { fparams.insert( fparams.begin(), - BObjectRef( new BConstObject( new BClassInstanceRef( - new BClassInstance( prog_, funcr->class_index(), Globals2 ) ) ) ) ); + BObjectRef( new BConstObject( new BClassInstanceRef( new BClassInstance( + prog_, funcr->class_index(), Globals2, pid() ) ) ) ) ); } } @@ -2967,7 +2967,7 @@ void Executor::jump( int target_PC, BContinuation* continuation, BFunctionRef* f } // Only store our global context if the function is external to the current program. - if ( funcref != nullptr && funcref->prog() != prog_ ) + if ( funcref != nullptr && funcref->pid() != pid() ) { // Store external context for the return path. rc.ExternalContext = ReturnContext::External( prog_, std::move( execmodules ), Globals2 ); @@ -3255,7 +3255,7 @@ void Executor::ins_double( const Instruction& ins ) void Executor::ins_classinst( const Instruction& ins ) { ValueStack.emplace_back( new BConstObject( - new BClassInstanceRef( new BClassInstance( prog_, ins.token.lval, Globals2 ) ) ) ); + new BClassInstanceRef( new BClassInstance( prog_, ins.token.lval, Globals2, pid() ) ) ) ); } void Executor::ins_string( const Instruction& ins ) @@ -3459,7 +3459,8 @@ void Executor::ins_funcref( const Instruction& ins ) auto funcref_index = static_cast( ins.token.lval ); - ValueStack.emplace_back( new BFunctionRef( prog_, funcref_index, Globals2, {} /* captures */ ) ); + ValueStack.emplace_back( + new BFunctionRef( prog_, pid(), funcref_index, Globals2, {} /* captures */ ) ); } void Executor::ins_functor( const Instruction& ins ) @@ -3478,7 +3479,7 @@ void Executor::ins_functor( const Instruction& ins ) capture_count--; } - auto func = new BFunctionRef( prog_, funcref_index, Globals2, std::move( captures ) ); + auto func = new BFunctionRef( prog_, pid(), funcref_index, Globals2, std::move( captures ) ); ValueStack.emplace_back( func ); diff --git a/pol-core/bscript/executor.h b/pol-core/bscript/executor.h index ac09047e9..815f532fb 100644 --- a/pol-core/bscript/executor.h +++ b/pol-core/bscript/executor.h @@ -518,6 +518,8 @@ public: bool empty_scriptname(); const EScriptProgram* prog() const; + virtual unsigned int pid() const { return 0; }; + private: ref_ptr prog_; bool prog_ok_; diff --git a/pol-core/bscript/object.cpp b/pol-core/bscript/object.cpp index f6b5850d0..0740ec980 100644 --- a/pol-core/bscript/object.cpp +++ b/pol-core/bscript/object.cpp @@ -2223,10 +2223,12 @@ std::string BBoolean::getStringRep() const return bval_ ? "true" : "false"; } -BFunctionRef::BFunctionRef( ref_ptr program, unsigned function_reference_index, +BFunctionRef::BFunctionRef( ref_ptr program, unsigned int pid, + unsigned function_reference_index, std::weak_ptr globals, ValueStackCont&& captures ) : BObjectImp( OTFuncRef ), prog_( std::move( program ) ), + original_pid_( pid ), function_reference_index_( function_reference_index ), globals( std::move( globals ) ), captures( std::move( captures ) ) @@ -2235,7 +2237,8 @@ BFunctionRef::BFunctionRef( ref_ptr program, unsigned function_r } BFunctionRef::BFunctionRef( const BFunctionRef& B ) - : BFunctionRef( B.prog_, B.function_reference_index_, B.globals, ValueStackCont( B.captures ) ) + : BFunctionRef( B.prog_, B.original_pid_, B.function_reference_index_, B.globals, + ValueStackCont( B.captures ) ) { } @@ -2378,6 +2381,11 @@ ref_ptr BFunctionRef::prog() const return prog_; } +unsigned int BFunctionRef::pid() const +{ + return original_pid_; +} + unsigned BFunctionRef::class_index() const { return prog_->function_references[function_reference_index_].class_index; diff --git a/pol-core/doc/core-changes.txt b/pol-core/doc/core-changes.txt index ee6c57daf..20d4a5341 100644 --- a/pol-core/doc/core-changes.txt +++ b/pol-core/doc/core-changes.txt @@ -1,4 +1,6 @@ -- POL100.3.0 -- +05-31-2026 Turley: + Fixed: When sending classes/functionobjects to the same script but different instance the wrong globals where used 05-25-2026 Turley: Fixed: Memoryleak when storing classes or functionobjects as global variable Changed: When sending classes/functionobjects to another script its no longer valid to access global variables when the sending script is destroyed before the call. diff --git a/pol-core/pol/uoexec.h b/pol-core/pol/uoexec.h index f793bba4e..94b2e00c1 100644 --- a/pol-core/pol/uoexec.h +++ b/pol-core/pol/uoexec.h @@ -123,7 +123,7 @@ public: void SleepFor( u32 secs ); void SleepForMs( u32 msecs ); - unsigned int pid() const; + unsigned int pid() const override; bool blocked() const; bool in_debugger_holdlist() const; void revive_debugged(); diff --git a/testsuite/pol/testpkgs/funcref/send_same_prog.src b/testsuite/pol/testpkgs/funcref/send_same_prog.src new file mode 100644 index 000000000..14cf0f548 --- /dev/null +++ b/testsuite/pol/testpkgs/funcref/send_same_prog.src @@ -0,0 +1,31 @@ +use os; + +var state; + +program prog( args ) + state := args[2]; + var parent := GetProcess( args[1] ); + if ( state == "main" ) + return spawn(); + else + parent.SendEvent( struct{ res := @() { return state; } } ); + Wait_For_Event( 1 ); + endif +endprogram + +function spawn() + var spawned := start_script( ":testfuncref:send_same_prog", { GetPid(), "secondary" } ); + + if ( !spawned ) + return $"failed to spawn: {spawned}"; + endif + + var ev := Wait_For_Event( 1 ); + if ( !ev ) + return $"no event: {ev}"; + endif + var res := ev.res.call(); + spawned.SendEvent( 1 ); + return res; +endfunction + diff --git a/testsuite/pol/testpkgs/funcref/test_call.src b/testsuite/pol/testpkgs/funcref/test_call.src index 3f99adbec..994212f84 100644 --- a/testsuite/pol/testpkgs/funcref/test_call.src +++ b/testsuite/pol/testpkgs/funcref/test_call.src @@ -152,6 +152,11 @@ exported function test_call_destroyed_globals() return ret_error( $"Unexpected event {ev}" ); endfunction +exported function test_call_sameprog() + var res := run_script( ":testfuncref:send_same_prog", { GetPid(), "main" } ); + return ret_error_not_equal( res, "secondary", $"wrong global capture: {res}" ); +endfunction + function user_func() glob := "glob set inside user_func"; return "return from user_func";