제로 론프 사용 C/C++ 응용 프로그램을 Linux로 포팅하려고하는데 D-BUS 관련 segfaults가 발생합니다. 이것이 Avahi의 버그, Avahi의 오용, 또는 제 코드의 버그인지는 확실하지 않습니다.다중 스레드 avahi 해결로 segfault가 발생합니다
AvahiClient, AvahiSimplePoll 및 AvahiServiceResolver를 캡슐화하는 ZeroconfResolver 개체를 사용하고 있습니다. ZeroconfResolver는 AvgiSimplePoll을 처음으로 인스턴스화 한 다음 Avaya 클라이언트, AvahiClient 및 AvahiServiceResolver를 먼저 인스턴스화하는 Resolve 함수를 가지고 있습니다. 각 인스턴스화에서 다음으로 진행하기 전에 오류를 검사하고 있습니다. AvahiServiceResolver가 성공적으로 생성 된 후 AvahiSimplePoll을 사용하여 avahi_simple_poll_loop을 호출합니다.
이 전체 프로세스는 여러 ZeroconfResolvers 비동기 같은 시에 사용되는 경우에 동 기적으로 수행하지만 세그먼테이션 폴트 (segfault)와 함께 실패 할 때 잘 작동합니다 (즉 내가 그들의 자신의 ZeroconfResolver 객체를 생성 다중 스레드를 가지고). 이 segfaults를 재생산하는 객체의 간단한 적용은 아래 코드에서 볼 수 있습니다. (바로 사용하지 않을 수도 있지만 사용 빈도는 자주 발생합니다).
나는 이해할 수를 Avahi [1]는만큼 그들은 입니다 같은 프로세스에서 여러 AvahiClient/AvahiPoll 개체가하는 것이 안전의 나의 해석에 따라 스레드 안전하지만, 되지 않는다 "상자 밖으로" 둘 이상의 스레드에서 '액세스'되지 않습니다. 각 ZeroconfResolver는 자신의 스레드 집합을 가로 질러 서로 상호 작용하지 않는 Avahi 객체 집합을 가지고 있습니다.
세그 폴트는 Avahi 라이브러리에서 임의의 기능으로 보이는 것처럼 보입니다. 일반적으로 dbah를 참조하는 avahi_client_new 또는 avahi_service_resolver_new 함수 내에서 발생합니다. Avahi 위키 은 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를 사용하는 것 외에는 선택의 여지가 없습니다 (제가 생각한 목표 시스템의 설치를 완전히 통제하지 않는 한). –