diff --git a/doc/meson.build b/doc/meson.build index 44fda2ab..c562b6d1 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -21,8 +21,16 @@ if vers.version_compare('< 2.26.0') error('Dot (Graphviz) 2.26 or later is required for building documentation, found @0@.'.format(vers)) endif +run_env = environment() +if catalog_path != '' + if not catalog_path.startswith('/') + catalog_path = meson.project_source_root() / catalog_path + endif + run_env.set('XML_CATALOG_FILES', catalog_path) +endif + manpage_xsl = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl' -cmd = run_command(xsltproc, '--nonet', manpage_xsl, check: false) +cmd = run_command(xsltproc, '--nonet', manpage_xsl, env: run_env, check: false) if cmd.returncode() != 0 error('The style sheet for man pages providing "@0@" was not found.'.format(manpage_xsl)) endif diff --git a/doc/publican/meson.build b/doc/publican/meson.build index 1aa31d3c..d247f94f 100644 --- a/doc/publican/meson.build +++ b/doc/publican/meson.build @@ -28,6 +28,7 @@ endforeach publican_inputs += custom_target( 'ProtocolSpec.xml', command: [ xsltproc, '-o', '@OUTPUT@', proto_to_docboox_xsl, '@INPUT@' ], + env: run_env, input: wayland_protocol_xml, output: 'ProtocolSpec.xml' ) @@ -35,6 +36,7 @@ publican_inputs += custom_target( publican_inputs += custom_target( 'ProtocolInterfaces.xml', command: [ xsltproc, '-o', '@OUTPUT@', proto_iface_to_docboox_xsl, '@INPUT@' ], + env: run_env, input: wayland_protocol_xml, output: 'ProtocolInterfaces.xml' ) @@ -45,6 +47,7 @@ publican_inputs += custom_target( ClientAPI_combined = custom_target( 'ClientAPI-combine-doxygen-files', command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ], + env: run_env, input: [ doxygen_Client_combine_xslt, doxygen_Client_index_xml ], output: 'ClientAPI-combined.xml' ) @@ -53,6 +56,7 @@ ClientAPI_combined = custom_target( publican_inputs += custom_target( 'ClientAPI-doxygen-to-docbook', command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Client', to_publican_xsl, '@INPUT@' ], + env: run_env, input: ClientAPI_combined, output: 'ClientAPI.xml' ) @@ -60,6 +64,7 @@ publican_inputs += custom_target( ServerAPI_combined = custom_target( 'ServerAPI-combine-doxygen-files', command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ], + env: run_env, input: [ doxygen_Server_combine_xslt, doxygen_Server_index_xml ], output: 'ServerAPI-combined.xml' ) @@ -67,6 +72,7 @@ ServerAPI_combined = custom_target( publican_inputs += custom_target( 'ServerAPI-doxygen-to-docbook', command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Server', to_publican_xsl, '@INPUT@' ], + env: run_env, input: ServerAPI_combined, output: 'ServerAPI.xml' ) @@ -88,6 +94,7 @@ foreach src : files([ merge_mapcoords_xsl, '@INPUT@', ], + env: run_env, input: src, output: [name], depends: publican_image_maps, @@ -108,6 +115,7 @@ custom_target( 'html', '@INPUT0@' ], + env: run_env, input: publican_inputs, output: 'html', build_by_default: true, diff --git a/egl/wayland-egl-symbols-check b/egl/wayland-egl-symbols-check index d04fd042..8049244e 100755 --- a/egl/wayland-egl-symbols-check +++ b/egl/wayland-egl-symbols-check @@ -14,7 +14,10 @@ if ! test -n "$NM"; then exit 99 fi -AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')" +case "$LIB" in + *.dylib) AVAIL_FUNCS="$($NM -g --format=bsd --defined-only $LIB | awk '{sub(/^_/,"",$3);print $3}')" ;; + *.so|*.so.*) AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')" ;; +esac # Official ABI, taken from the header. REQ_FUNCS="wl_egl_window_resize diff --git a/meson.build b/meson.build index 7ad5ac06..5dd0aeee 100644 --- a/meson.build +++ b/meson.build @@ -20,7 +20,9 @@ config_h.set_quoted('PACKAGE', meson.project_name()) config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) cc_args = [] -if host_machine.system() not in ['freebsd', 'openbsd'] +if host_machine.system() == 'darwin' + cc_args += ['-D_DARWIN_C_SOURCE'] +elif host_machine.system() not in ['freebsd', 'openbsd'] cc_args += ['-D_POSIX_C_SOURCE=200809L'] endif add_project_arguments(cc_args, language: 'c') @@ -73,10 +75,17 @@ if host_machine.system() == 'freebsd' endif config_h.set10('HAVE_BROKEN_MSG_CMSG_CLOEXEC', have_broken_msg_cmsg_cloexec) +has_itimerspec = cc.has_type( + 'struct itimerspec', + prefix: '#include ', + args: '-D_POSIX_C_SOURCE=200809L' +) +config_h.set('HAVE_ITIMERSPEC', has_itimerspec) + if get_option('libraries') - if host_machine.system() in ['freebsd', 'openbsd'] - # When building for FreeBSD, epoll(7) is provided by a userspace - # wrapper around kqueue(2). + if host_machine.system() in ['freebsd', 'openbsd', 'darwin'] + # When building for FreeBSD, OpenBSD or Darwin, epoll(7) is provided + # by a userspace wrapper around kqueue(2). epoll_dep = dependency('epoll-shim') else # Otherwise, assume that epoll(7) is supported natively. @@ -112,6 +121,8 @@ configure_file( wayland_protocol_xml = files('protocol/wayland.xml') +catalog_path = get_option('xml_catalog') + root_inc = include_directories('.') protocol_inc = include_directories('protocol') src_inc = include_directories('src') diff --git a/meson_options.txt b/meson_options.txt index b8e2ec60..77f3ea30 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -14,6 +14,10 @@ option('documentation', description: 'Build the documentation (requires Doxygen, dot, xmlto, xsltproc)', type: 'boolean', value: true) +option('xml_catalog', + description: 'Path to XML catalog file', + type: 'string', + value: '') option('dtd_validation', description: 'Validate the protocol DTD (requires libxml2)', type: 'boolean', diff --git a/src/connection.c b/src/connection.c index 2d1e8d1d..689320c1 100644 --- a/src/connection.c +++ b/src/connection.c @@ -316,6 +316,19 @@ wl_connection_set_max_buffer_size(struct wl_connection *connection, ring_buffer_ensure_space(&connection->out, 0); } +#ifdef __APPLE__ +static int fd_setfl_nonblock(int fd) +{ + int flags; + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) + return flags; + + return fcntl(fd, F_SETFL, flags | O_NONBLOCK); +} +#endif + struct wl_connection * wl_connection_create(int fd, size_t max_buffer_size) { @@ -329,6 +342,10 @@ wl_connection_create(int fd, size_t max_buffer_size) connection->fd = fd; +#ifdef __APPLE__ + fd_setfl_nonblock(fd); +#endif + return connection; } diff --git a/src/event-loop.c b/src/event-loop.c index 89294fd9..9db4f114 100644 --- a/src/event-loop.c +++ b/src/event-loop.c @@ -23,6 +23,8 @@ * SOFTWARE. */ +#include "../config.h" + #include #include #include @@ -45,6 +47,13 @@ #include "wayland-server-private.h" #include "wayland-os.h" +#ifndef HAVE_ITIMERSPEC +struct itimerspec { + struct timespec it_interval; + struct timespec it_value; +}; +#endif + /** \cond INTERNAL */ #define TIMER_REMOVED -2 diff --git a/src/wayland-client.c b/src/wayland-client.c index ed686b5c..d701595f 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/src/wayland-os.c b/src/wayland-os.c index f00ead4b..5c1d8c3d 100644 --- a/src/wayland-os.c +++ b/src/wayland-os.c @@ -75,17 +75,19 @@ wl_os_socket_cloexec(int domain, int type, int protocol) { int fd; +#ifdef SOCK_CLOEXEC fd = wl_socket(domain, type | SOCK_CLOEXEC, protocol); if (fd >= 0) return fd; if (errno != EINVAL) return -1; +#endif fd = wl_socket(domain, type, protocol); return set_cloexec_or_close(fd); } -#if defined(__FreeBSD__) +#if defined(LOCAL_PEERCRED) int wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) { @@ -101,11 +103,15 @@ wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) #if HAVE_XUCRED_CR_PID /* Since https://cgit.freebsd.org/src/commit/?id=c5afec6e895a */ *pid = ucred.cr_pid; +#elif defined(LOCAL_PEERPID) + if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERPID, pid, &len) < 0) + *pid = 0; #else *pid = 0; #endif return 0; } + #elif defined(SO_PEERCRED) int wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) @@ -125,6 +131,7 @@ wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) *pid = ucred.pid; return 0; } + #else #error "Don't know how to read ucred on this platform" #endif @@ -186,7 +193,7 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) * fix (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211). */ #pragma message("Using fallback directly since MSG_CMSG_CLOEXEC is broken.") -#else +#elif defined(MSG_CMSG_CLOEXEC) ssize_t len; len = wl_recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC); @@ -220,7 +227,8 @@ wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int fd; -#ifdef HAVE_ACCEPT4 +#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) + fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC); if (fd >= 0) return fd; diff --git a/tests/client-test.c b/tests/client-test.c index 5585c0cd..39fc9403 100644 --- a/tests/client-test.c +++ b/tests/client-test.c @@ -97,7 +97,7 @@ TEST(client_destroy_listener) bool user_data_destroyed = false; int s[2]; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); @@ -184,7 +184,7 @@ TEST(client_destroy_removes_link) struct client_destroy_listener destroy_listener; int s[2]; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); diff --git a/tests/connection-test.c b/tests/connection-test.c index aed97a0a..0ffd964e 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -48,7 +48,7 @@ setup(int *s) { struct wl_connection *connection; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); connection = wl_connection_create(s[0], WL_BUFFER_DEFAULT_MAX_SIZE); assert(connection); @@ -181,8 +181,7 @@ struct marshal_data { static void setup_marshal_data(struct marshal_data *data) { - assert(socketpair(AF_UNIX, - SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, data->s) == 0); data->read_connection = wl_connection_create(data->s[0], WL_BUFFER_DEFAULT_MAX_SIZE); assert(data->read_connection); @@ -885,7 +884,7 @@ TEST(request_bogus_size) for (bogus_size = 11; bogus_size >= 0; bogus_size--) { fprintf(stderr, "* bogus size %d\n", bogus_size); - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c index 061d29e6..4314ffd6 100644 --- a/tests/os-wrappers-test.c +++ b/tests/os-wrappers-test.c @@ -61,10 +61,12 @@ socket_wrapper(int domain, int type, int protocol) { wrapped_calls_socket++; +#ifdef SOCK_CLOEXEC if (fall_back && (type & SOCK_CLOEXEC)) { errno = EINVAL; return -1; } +#endif return socket(domain, type, protocol); } @@ -110,10 +112,12 @@ recvmsg_wrapper(int sockfd, struct msghdr *msg, int flags) { wrapped_calls_recvmsg++; +#ifdef MSG_CMSG_CLOEXEC if (fall_back && (flags & MSG_CMSG_CLOEXEC)) { errno = EINVAL; return -1; } +#endif return recvmsg(sockfd, msg, flags); } @@ -170,12 +174,14 @@ TEST(os_wrappers_socket_cloexec) do_os_wrappers_socket_cloexec(0); } +#ifdef MSG_CMSG_CLOEXEC TEST(os_wrappers_socket_cloexec_fallback) { /* forced fallback */ init_fallbacks(1); do_os_wrappers_socket_cloexec(1); } +#endif static void do_os_wrappers_dupfd_cloexec(int n) @@ -232,8 +238,7 @@ struct marshal_data { static void setup_marshal_data(struct marshal_data *data) { - assert(socketpair(AF_UNIX, - SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, data->s) == 0); data->read_connection = wl_connection_create(data->s[0], WL_BUFFER_DEFAULT_MAX_SIZE); @@ -350,11 +355,13 @@ TEST(os_wrappers_recvmsg_cloexec) do_os_wrappers_recvmsg_cloexec(0); } +#ifdef MSG_CMSG_CLOEXEC TEST(os_wrappers_recvmsg_cloexec_fallback) { init_fallbacks(1); do_os_wrappers_recvmsg_cloexec(1); } +#endif static void do_os_wrappers_epoll_create_cloexec(int n) diff --git a/tests/queue-test.c b/tests/queue-test.c index 7dfdd306..a000a347 100644 --- a/tests/queue-test.c +++ b/tests/queue-test.c @@ -44,6 +44,17 @@ #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +#ifdef __APPLE__ +static void *memrchr(const void *s, int c, size_t n) { + const unsigned char *p = (const unsigned char *)s; + while (n--) { + if (p[n] == (unsigned char)c) + return (void *)(p + n); + } + return NULL; +} +#endif + static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) diff --git a/tests/resources-test.c b/tests/resources-test.c index 92707297..13d267da 100644 --- a/tests/resources-test.c +++ b/tests/resources-test.c @@ -40,7 +40,7 @@ TEST(create_resource_tst) int s[2]; uint32_t id; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); @@ -111,7 +111,7 @@ TEST(destroy_res_tst) .notify = &destroy_notify }; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); @@ -159,7 +159,7 @@ TEST(create_resource_with_same_id) int s[2]; uint32_t id; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); @@ -243,7 +243,7 @@ TEST(resource_destroy_iteration) .notify = &resource_destroy_notify }; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); diff --git a/tests/test-runner.c b/tests/test-runner.c index 9a50d1dd..28439c9b 100644 --- a/tests/test-runner.c +++ b/tests/test-runner.c @@ -36,9 +36,11 @@ #include #include #include +#include #include #include #include +#include #ifdef HAVE_SYS_PROCCTL_H #include #elif defined(HAVE_SYS_PRCTL_H) @@ -46,6 +48,8 @@ #ifndef PR_SET_PTRACER # define PR_SET_PTRACER 0x59616d61 #endif +#elif defined(__APPLE__) +#include #endif #include "test-runner.h" @@ -63,7 +67,12 @@ static int timeouts_enabled = 1; /* set to one if the output goes to the terminal */ static int is_atty = 0; +#ifdef __APPLE__ +extern const struct test __start_test_section __asm("section$start$__DATA$test_section"); +extern const struct test __stop_test_section __asm("section$end$__DATA$test_section"); +#else extern const struct test __start_test_section, __stop_test_section; +#endif static const struct test * find_test(const char *name) @@ -308,6 +317,22 @@ is_debugger_attached(void) return rc; } +#elif defined(__APPLE__) +static int +is_debugger_attached(void) +{ + int ret; + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; + struct kinfo_proc info; + size_t size; + + info.kp_proc.p_flag = 0; + ret = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); + assert(ret == 0); + + return (info.kp_proc.p_flag & P_TRACED) != 0; +} + #else static int is_debugger_attached(void) @@ -317,6 +342,43 @@ is_debugger_attached(void) } #endif +int +socketpair_cloexec(int domain, int type, int protocol, int sv[2]) +{ + int flags; + +#ifdef SOCK_CLOEXEC + if (socketpair(domain, type | SOCK_CLOEXEC, protocol, sv) == 0) + return 0; + if (errno != EINVAL) + return -1; +#endif + + if (socketpair(domain, type, protocol, sv) < 0) + return -1; + + flags = fcntl(sv[0], F_GETFD); + if (flags < 0) + goto err; + + if (fcntl(sv[0], F_SETFD, flags | FD_CLOEXEC) < 0) + goto err; + + flags = fcntl(sv[1], F_GETFD); + if (flags < 0) + goto err; + + if (fcntl(sv[1], F_SETFD, flags | FD_CLOEXEC) < 0) + goto err; + + return 0; + +err: + close(sv[0]); + close(sv[1]); + return -1; +} + int main(int argc, char *argv[]) { const struct test *t; diff --git a/tests/test-runner.h b/tests/test-runner.h index d0734009..6fbf57b4 100644 --- a/tests/test-runner.h +++ b/tests/test-runner.h @@ -37,11 +37,17 @@ struct test { int must_fail; } __attribute__ ((aligned (16))); +#ifdef __APPLE__ +#define TEST_SECTION "__DATA,test_section" +#else +#define TEST_SECTION "test_section" +#endif + #define TEST(name) \ static void name(void); \ \ const struct test test##name \ - __attribute__ ((used, section ("test_section"))) = { \ + __attribute__ ((used, section (TEST_SECTION))) = { \ #name, name, 0 \ }; \ \ @@ -51,7 +57,7 @@ struct test { static void name(void); \ \ const struct test test##name \ - __attribute__ ((used, section ("test_section"))) = { \ + __attribute__ ((used, section (TEST_SECTION))) = { \ #name, name, 1 \ }; \ \ @@ -86,6 +92,9 @@ test_sleep(unsigned int); void test_disable_coredumps(void); +int +socketpair_cloexec(int domain, int type, int protocol, int sv[2]); + #define DISABLE_LEAK_CHECKS \ do { \ extern int fd_leak_check_enabled; \