Я пытаюсь перенести приложение с поддержкой C/C++ с поддержкой zeronconf в Linux, однако я получаю связанные с D-BUS segfaults. Я не уверен, что это ошибка в Avahi, неправильное использование Avahi или ошибка в моем коде.многопоточные решения разрешения avahi segfault
Я использую объект ZeroconfResolver, который инкапсулирует AvahiClient, AvahiSimplePoll и AvahiServiceResolver. ZeroconfResolver имеет функцию Resolve, которая сначала создает экземпляр AvahiSimplePoll, затем AvahiClient и, наконец, AvahiServiceResolver. При каждом экземпляре я проверяю ошибки, прежде чем переходить к следующему. После того, как AvahiServiceResolver был успешно создан, он вызывает avahi_simple_poll_loop с AvahiSimplePoll.
Весь этот процесс прекрасно работает, когда сделано синхронно, но не с , когда несколько ошибкой сегментации ZeroconfResolvers используется в то же время асинхронно (то есть у меня есть несколько потоков, создавая свои собственные ZeroconfResolver объектов). Тривиальная адаптация объекта, которую воспроизводит segfaults, может быть видна в приведенном ниже коде (может не сразу выполнить segfault , но в моем случае это случается часто).
Я понимаю, что «из коробки» Avahi не Потокобезопасная, но согласно моей интерпретации [1] безопасно иметь несколько AvahiClient/AvahiPoll объектов в том же процессе, пока они не «доступ» из нескольких потоков. Каждый ZeroconfResolver имеет свой собственный набор объектов Avahi, которые не взаимодействуют друг с другом через границы потоков.
Segfaults происходят в кажущихся случайными функциями в библиотеке Avahi . В общем случае они происходят в функциях avahi_client_new или avahi_service_resolver_new, ссылающихся на dbus. Предполагается ли, что Avaji wiki означает, что «создание» объектов AvahiClient/AvahiPoll равно , а также небезопасный поток?
[1] http://avahi.org/wiki/RunningAvahiClientAsThread
#include <dispatch/dispatch.h>
#include <cstdio>
#include <sys/types.h>
#include <netinet/in.h>
#include <avahi-client/lookup.h>
#include <avahi-client/client.h>
#include <avahi-client/publish.h>
#include <avahi-common/alternative.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/timeval.h>
void resolve_reply(
AvahiServiceResolver *r,
AVAHI_GCC_UNUSED AvahiIfIndex interface,
AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiResolverEvent event,
const char *name,
const char *type,
const char *domain,
const char *host_name,
const AvahiAddress *address,
uint16_t port,
AvahiStringList *txt,
AvahiLookupResultFlags flags,
void * context) {
assert(r);
if (event == AVAHI_RESOLVER_FOUND)
printf("resolve_reply(%s, %s, %s, %s)[FOUND]\n", name, type, domain, host_name);
avahi_service_resolver_free(r);
avahi_simple_poll_quit((AvahiSimplePoll*)context);
}
int main() {
// Run until segfault
while (true) {
// Adding block to conccurent GCD queue (managed thread pool)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), [=]{
char name[] = "SomeHTTPServerToResolve";
char domain[] = "local.";
char type[] = "_http._tcp.";
AvahiSimplePoll * simple_poll = NULL;
if ((simple_poll = avahi_simple_poll_new())) {
int error;
AvahiClient * client = NULL;
if ((client = avahi_client_new(avahi_simple_poll_get(simple_poll), AVAHI_CLIENT_NO_FAIL, NULL, NULL, &error))) {
AvahiServiceResolver * resolver = NULL;
if ((resolver = avahi_service_resolver_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, name, type, domain, AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_NO_ADDRESS, (AvahiServiceResolverCallback)resolve_reply, simple_poll))) {
avahi_simple_poll_loop(simple_poll);
printf("Exit Loop(%p)\n", simple_poll);
} else {
printf("Resolve(%s, %s, %s)[%s]\n", name, type, domain, avahi_strerror(avahi_client_errno(client)));
}
avahi_client_free(client);
} else {
printf("avahi_client_new()[%s]\n", avahi_strerror(error));
}
avahi_simple_poll_free(simple_poll);
} else {
printf("avahi_simple_poll_new()[Failed]\n");
}
});
}
// Never reached
return 0;
}
ли вам решить это? –
@JohanLundberg Nope. Я сдался и решил собрать во встроенной версии Bonjour. В качестве руководства я использовал проект uMundo с открытым исходным кодом. Не обязательно простая задача, но, возможно, мой единственный шаг, поскольку сообщество Avahi, кажется, умирает (почти все вопросы остаются без ответа в рассылке, создатели молчат). Если эта тенденция сохранится, я думаю, что дистрибутивы Linux должны переключаться. – BigMacAttack
В системе не может быть более одного ответчика Zeroconf. Таким образом, у вас действительно нет выбора, кроме как использовать Avahi в системах Linux (если вы не имеете полного контроля над установками целевых систем, я полагаю). –