Skip to content

Commit

Permalink
Improve IPC TL stacktrace
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed Dec 15, 2023
1 parent 1dde960 commit 27addd1
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 57 deletions.
1 change: 1 addition & 0 deletions src/Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function __construct($message = null, $code = 0, ?\Throwable $previous =
}
parent::__construct($message, $code, $previous);
if (!str_contains($message, 'socket_accept')
&& $message !== 'Client backtrace'
&& !\in_array(basename($this->file), ['PKCS8.php', 'PSS.php'], true)
) {
Logger::log($message.' in '.basename($this->file).':'.$this->line, Logger::FATAL_ERROR);
Expand Down
103 changes: 46 additions & 57 deletions src/Ipc/ExitFailure.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@

namespace danog\MadelineProto\Ipc;

use danog\MadelineProto\RPCErrorException;
use danog\MadelineProto\TL\Exception;
use ReflectionObject;
use RuntimeException;
use danog\MadelineProto\Exception as MadelineProtoException;
use ReflectionClass;
use Throwable;

use function Amp\Parallel\Context\flattenThrowableBacktrace as ContextFlattenThrowableBacktrace;
Expand All @@ -29,75 +27,66 @@
*/
final class ExitFailure
{
/** @var class-string<\Throwable> */
private string $type;

private string $message;

private string $file;

private int $line;

private int|string $code;

/** @var list<array<non-empty-string, list<scalar>|scalar>> */
private array $trace;

private ?string $tlTrace = null;
private array $props;

private ?self $previous = null;

private ?string $localized = null;

public function __construct(Throwable $exception)
{
$this->type = $exception::class;
$this->message = $exception->getMessage();
$this->code = $exception->getCode();
$this->file = $exception->getFile();
$this->line = $exception->getLine();
$this->trace = ContextFlattenThrowableBacktrace($exception);
if (method_exists($exception, 'getTLTrace')) {
$this->tlTrace = $exception->getTLTrace();
}

if ($exception instanceof RPCErrorException) {
$this->localized = $exception->getLocalization();
}
$props = [];
$f = new ReflectionClass($exception);
do {
foreach ($f->getProperties() as $prop) {
if ($prop->isStatic()) {
continue;
}
$value = $prop->getValue($exception);
if ($prop->getName() === 'trace' && \is_array($value)) {
$value = ContextFlattenThrowableBacktrace($exception);
} elseif ($prop->getName() === 'previous' && $value instanceof \Throwable) {
$value = new self($value);
}
$props[$f->getName()][$prop->getName()] = $value;
}
} while ($f = $f->getParentClass());

if ($previous = $exception->getPrevious()) {
$this->previous = new self($previous);
}
$this->props = $props;
}

public function getException(): object
{
$previous = $this->previous ? $this->previous->getException() : null;

try {
if ($this->type === Exception::class) {
$exception = new $this->type($this->message);
} else {
$exception = new $this->type($this->message, $this->code, $previous);
}
} catch (Throwable $e) {
$exception = new RuntimeException($this->message, $this->code, $previous);
}

$refl = new ReflectionObject($exception);
foreach (['trace', 'line', 'file'] as $prop) {
try {
$trace = $refl->getProperty($prop);
$trace->setValue($exception, $this->{$prop});
} catch (Throwable) {
$prev = new MadelineProtoException("Client backtrace");

$refl = new \ReflectionClass($this->type);
$exception = $refl->newInstanceWithoutConstructor();

$props = $this->props;
$props[\Exception::class]['previous'] = $this->previous?->getException();

foreach ($props as $class => $subprops) {
$class = new ReflectionClass($class);
foreach ($subprops as $key => $value) {
if ($key === 'previous') {
if ($value instanceof self) {
$value = $value->getException();
} elseif ($value === null) {
$value = $prev;
}
} elseif ($key === 'tlTrace') {
$value = "$value\n\nClient TL trace:".$prev->getTLTrace();
}
try {
$key = $refl->getProperty($key);
$key->setValue($exception, $value);
} catch (\Throwable) {
}
}
}

if ($this->tlTrace && method_exists($exception, 'setTLTrace')) {
$exception->setTLTrace($this->tlTrace);
}
if ($this->localized && method_exists($exception, 'setLocalization')) {
$exception->setLocalization($this->localized);
}
return $exception;
}
}

0 comments on commit 27addd1

Please sign in to comment.