Source-Python-Dev-Team / Source.Python

This plugin aims to use boost::python and create an easily accessible wrapper around the Source Engine API for scripter use.
http://forums.sourcepython.com
GNU General Public License v3.0
163 stars 31 forks source link

Crash when accessing Entity.physics_object #357

Closed vinci6k closed 4 years ago

vinci6k commented 4 years ago

While messing around with props in HL2DM, it appears I stumbled upon an issue related to the internal caching system. The server crashes when you try to get the PhysicsObject of a prop_physics_respawnable entity after it respawns. Here's the code I used:

# ../physics_object_test/physics_object_test.py

# Source.Python
from commands import CommandReturn
from commands.client import ClientCommand
from entities.constants import MoveType
from mathlib import Vector
from players.entity import Player

FORCE = Vector(0, 0, 500)

@ClientCommand('push_up')
def push_up_cmd(command, index):
    player = Player(index)
    entity = player.view_entity

    # Is this a physical object?
    if entity.move_type == MoveType.VPHYSICS:
        # Push it up.
        entity.physics_object.apply_force_center(
            FORCE * entity.physics_object.mass)

    return CommandReturn.BLOCK

Basically, use the push_up command on any breakable prop, destroy it, and when it respawns - use the command again. This will result in a crash (https://www.youtube.com/watch?v=xFOaoMnlcNI - got lucky in the video, usually it crashes after the first respawn).

As for why I believe this to be an issue with the internal caching system - the entity (prop_physics_respawnable) doesn't get removed when it's destroyed, just hidden. Which means the entity itself is always within the cache. Here's the catch though, the PhysicsObject tied to the entity does get removed - as can be seen in CPhysicsPropRespawnable::Event_Killed(). Thus the physics_object property no longer points at the correct instance.

jordanbriere commented 4 years ago

As for why I believe this to be an issue with the internal caching system

This sounds plausible, though easy to confirm. If you add del entity.physics_object after your apply_force_center call and it no longer crash, then that means this is indeed what is happening.

vinci6k commented 4 years ago

I get an exception when I try that:

[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\packages\source-python\commands\auth.py", line 44, in __call__
    return self.callback(*args)
  File "..\addons\source-python\plugins\physics_object_test\physics_object_test.py", line 25, in push_up_cmd
    del entity.physics_object

AttributeError: can't delete attribute

Just in case it comes up, I am using the latest SP version:

--------------------------------------------------------
Checksum      : ef80b64ae09d908238b8860746606208
Date          : 2020-10-20 19:16:05.613435
OS            : Windows-10-10.0.19041
Game          : hl2dm
SP version    : 701
Github commit : f9d71cec67ef3662df07d579bba68fedea0558ad
Server plugins:
   00: Source.Python, (C) 2012-2020, Source.Python Team.
SP plugins:
   00: physics_object_test
--------------------------------------------------------
jordanbriere commented 4 years ago

Ah yeah, that's because the original is read-only, so its deleter is wrapped and raise. Try this instead: del entity.__dict__['physics_object']

vinci6k commented 4 years ago

That works. And the server no longer crashes! 😄

jordanbriere commented 4 years ago

That works. And the server no longer crashes! 😄

Awesome! Then the fix is as easy as removing this line. Feel free to PR that! :)