Ocramius/ProxyManager

Directly invoking proxy within pre hook crashes terminal

nmeri17 opened this issue · 2 comments

I have a high-level function that allows consumers run arbitrary functions before target methods.

foreach ($baseActions as $hooker => $action)

	$hookers[$hooker] = function ($proxy, $concrete, $calledMethod, $parameters, &$earlyReturn) use ($action) {

		$earlyReturn = true; // since handlers want to take responsibility of calling underlying concrete, not ProxyManager

		return call_user_func_array($action, [

			$concrete,

			$calledMethod, $parameters
		]);
	};

One of such arbitrary functionality involves a handler that does something similar to the following

public function safeCall (Failable $target, string $method, $parameters) { // safeCall is passed to $baseActions
	
	try {

		return call_user_func_array([$target, $method], $parameters);
	}
	catch (\Throwable $e) {

		// do something with $e

		// use nullObjectFactory to prepare some dummy result based on $target->$method return type

		$target->failedOperation($method);

		return $dummyResult;
	}
}

All other handlers work correctly, except this one with the line $target->failedOperation($method);. When I was using AccessInterceptorValueHolderFactory, safeCall received parent/original object. By the time user-land caller tries reading $target->getLastFailed();, it's now looking at a proxy where that property is null

trait FailableTrait {

	protected $erroneousMethod; // always null!!

	public function getLastFailed ():?string {

		return $this->erroneousMethod;
	}

	public function failedOperation (string $method):void {

		$this->erroneousMethod = $method;
	}
}

Now, if I switch the proxy from AccessInterceptorValueHolderFactory to AccessInterceptorScopeLocalizerFactory or if I pass $proxy instead of $concrete so handler can mutate what's passed to user-land, test terminal/CLI crashes every time this line executes call_user_func_array([$target, $method], $parameters);

How do you suggest I invoke target within a sandbox while mutating target?

I can confirm that terminal crashing was of my own making. It's unfortunate that neither the library nor php was able to detect max call stack and shutdown gracefully like it does with fatal errors

I faintly recall reading a warning not to invoke proxy within the handler, but I don't remember where. That turned out to be the reason behind the recursion crashing terminal. I call the returned proxy, it delegates to my handler, which in turn calls the same method on proxy in a vicious cycle

So, in order to manually invoke proxy, I passed it as additional method to safeCall, but instead of calling it again, I call $concrete. Then, in the try catch, I call failedOperation on the proxy since that's the instance that will be read in user land

neither the library nor php was able to detect max call stack and shutdown gracefully like it does with fatal errors

AFAIK, only XDebug does that.