perl: столкновение имени функции - PullRequest
2 голосов
/ 26 декабря 2011

Допустим, есть два модуля нашей инфраструктуры: Handler.pm и Queries.pm

Queries.pm не является обязательным и загружается при запуске процесса fastcgi

BEGIN {
&{"check_module_$_"}        () foreach (Queries);

}

sub check_module_queries {
...
    require Eludia::Content::Queries;
...
}

каждая функция модуля загружается в одно общее пространство имен

теперь есть две функции с одинаковым именем (setup_page_content) в Handler.pm и Queries.pm

вызывается setup_page_content в Handler.pm

Похоже, оригинальный автор предположил, что Queries.pm:setup_page_content будет вызываться всякий раз, когда загружается Queries.pm

Иногда этого не происходит: traceback (полученный через caller ()) в этих случаях указывает, что setup_page_content был вызван из модуля Handler.pm

Я зарегистрировал% INC непосредственно перед вызовом, и он содержит Queries.pm и полный путь в этих случаях

Это поведение противоречиво и появляется, как в 2-3% попыток при промышленной установке, в основном, когда я отправляю два параллельных идентичных http-запроса. Из-за большого количества усилий по воспроизведению, я пока не определяю, относится ли это к конкретной установке.

Как будет решаться, какая версия функции с тем же именем будет вызываться?

Это хорошо определенное поведение?

Должна быть причина, автор написал код таким образом

UPDATE

версия perl v5.10.1 built for x86_64-linux-gnu-thread-multi

ОБНОВЛЕНИЕ 2

код: Handler.pm и Queries.pm

Загрузка Queries.pm происходит в check_module_queries (BEGIN {} из Eludia.pm ),

загружается для каждого запроса, используя Loader.pm (через use Loader.pm <params>)

Ответы [ 4 ]

5 голосов
/ 26 декабря 2011
Я бы хотел вызывать Custom.pm:setup_page_content каждый раз, когда загружается Custom.pm

Так что вы хотите позвонить Custom::setup_page_content, когда он существует.

if (exists(&Custom::setup_page_content)) {
   Custom::setup_page_content(...);
} else {
   Handler::setup_page_content(...);
}

Иногда этого не происходит.

Полное отсутствие информации об этом мешает мне комментировать.Код?Что-нибудь?


Есть ли способ «выгрузить» модуль, но оставить его в% INC?

Загрузка модуля просто запускает его.Вы не можете "убрать" код.В лучшем случае вы можете вручную отменить некоторые из эффектов его запуска.Включает ли это изменение %INC или нет, зависит только от вас.

4 голосов
/ 13 января 2012

В случае коллизии пространства имен, последняя определенная / загруженная функция будет иметь приоритет.

2 голосов
/ 15 января 2012

Это не правильные модули. Это просто библиотеки. Если вы превратите их в правильные модули с правильным интервалом имен, у вас не будет этой проблемы. Вам едва нужно делать что-то большее, чем:

Пакет Queries;

sub new {

my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};

bless ( $self, $class );

return $self;

}

И вы будете в пути. Конечно, вашей программе потребуется пара изменений, чтобы получить доступ к функциям класса. Вы можете посмотреть на экспорт в функции, чтобы сэкономить время на рефакторинг.

Я разбудил код на github и инициировал запрос на удаление, который, надеюсь, решит вашу проблему.

0 голосов
/ 15 января 2012

Поведение совершенно определено: когда вы вызываете PACKAGENAME :: имя_функции, вызывается PACKAGENAME :: имя_функции.Одновременно может быть не более одного PACKAGENAME :: function_name.

Можно переопределять каждую функцию столько раз, сколько вы пожелаете.Когда вы, скажем, выполняете некоторый код, такой как

eval "sub PACKAGENAME::function_name {...}";

, функция [re] определена.Когда вы require какой-то .pm файл, это очень похоже на eval строку с ее содержимым.

Если PACKAGENAME не определено явно, используется значение __PACKAGE__.

Поэтому, если вы заметите, что версия setup_page_content взята из Handler.pm, она должна указывать, что контент Handler.pm был выполнен (use, require, read / eval и т. Д.)после загрузки Queries.pm (в последний раз).

Таким образом, вы должны отслеживать все события загрузки Handler.pm.Самый простой способ - добавить отладочную печать в начале Handler.pm.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...