Hi,

at first glance I didn't like returning fd from wl_connection_destroy, but
at the other, I did!
If you think about the connection as a buffer for the fd (and that is
really the case),
then it make sense to do something like:

      create conn      ------------------     destroy conn
fd ----------------------> | connection | ------------------------> fd
                             ------------------

The race in threaded environment is real (one thread closes fd, say 6,
other thread opens new fd
- it will get the first free value which is 6 - and the first thread close
the 6 again and we're in trouble..)
So it's important to close every fd only once.

For me it's OK and:

Reviewed-by: Marek Chalupa <mchqwe...@gmail.com>

On 30 September 2014 14:43, Benjamin Herr <b...@0x539.de> wrote:

> Calling close() on the same file descriptor that a previous call to
> close() already closed is wrong, and racy if another thread received
> that same file descriptor as a eg. new socket or actual file.
>
> There are two situations where wl_connection_destroy() would close its
> file descriptor and then another function up in the call chain would
> close the same file descriptor:
>
>   * When wl_client_create() fails after calling wl_connection_create(),
>     it will call wl_connection_destroy() before returning. However, its
>     caller will always close the file descriptor if wl_client_create()
>     fails.
>
>   * wl_display_disconnect() unconditionally closes the display file
>     descriptor and also calls wl_connection_destroy().
>
> So these two seem to expect wl_connection_destroy() to leave the file
> descriptor open. The other caller of wl_connection_destroy(),
> wl_client_destroy(), does however expect wl_connection_destroy() to
> close its file descriptor, alas.
>
> This patch changes wl_connection_destroy() to indulge this majority of
> two callers by simply not closing the file descriptor. For the benefit
> of wl_client_destroy(), wl_connection_destroy() then returns the
> unclosed file descriptor so that wl_client_destroy() can close it
> itself.
>
> Since wl_connection_destroy() is a private function called from few
> places, changing its semantics seemed like the more expedient way to
> address the double-close() problem than shuffling around the logic in
> wl_client_create() to somehow enable it to always avoid calling
> wl_connection_destroy().
>
> Signed-off-by: Benjamin Herr <b...@0x539.de>
> ---
>  src/connection.c        | 7 +++++--
>  src/wayland-private.h   | 2 +-
>  src/wayland-server.c    | 2 +-
>  tests/connection-test.c | 8 ++++++--
>  4 files changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/src/connection.c b/src/connection.c
> index f292853..c5daca6 100644
> --- a/src/connection.c
> +++ b/src/connection.c
> @@ -189,13 +189,16 @@ close_fds(struct wl_buffer *buffer, int max)
>         buffer->tail += size;
>  }
>
> -void
> +int
>  wl_connection_destroy(struct wl_connection *connection)
>  {
> +       int fd = connection->fd;
> +
>         close_fds(&connection->fds_out, -1);
>         close_fds(&connection->fds_in, -1);
> -       close(connection->fd);
>         free(connection);
> +
> +       return fd;
>  }
>
>  void
> diff --git a/src/wayland-private.h b/src/wayland-private.h
> index 67e8783..db76081 100644
> --- a/src/wayland-private.h
> +++ b/src/wayland-private.h
> @@ -86,7 +86,7 @@ int wl_interface_equal(const struct wl_interface *iface1,
>                        const struct wl_interface *iface2);
>
>  struct wl_connection *wl_connection_create(int fd);
> -void wl_connection_destroy(struct wl_connection *connection);
> +int wl_connection_destroy(struct wl_connection *connection);
>  void wl_connection_copy(struct wl_connection *connection, void *data,
> size_t size);
>  void wl_connection_consume(struct wl_connection *connection, size_t size);
>
> diff --git a/src/wayland-server.c b/src/wayland-server.c
> index 674aeca..7caeb30 100644
> --- a/src/wayland-server.c
> +++ b/src/wayland-server.c
> @@ -670,7 +670,7 @@ wl_client_destroy(struct wl_client *client)
>         wl_map_for_each(&client->objects, destroy_resource, &serial);
>         wl_map_release(&client->objects);
>         wl_event_source_remove(client->source);
> -       wl_connection_destroy(client->connection);
> +       close(wl_connection_destroy(client->connection));
>         wl_list_remove(&client->link);
>         free(client);
>  }
> diff --git a/tests/connection-test.c b/tests/connection-test.c
> index 659bf68..4497128 100644
> --- a/tests/connection-test.c
> +++ b/tests/connection-test.c
> @@ -57,6 +57,7 @@ TEST(connection_create)
>
>         connection = setup(s);
>         wl_connection_destroy(connection);
> +       close(s[0]);
>         close(s[1]);
>  }
>
> @@ -74,6 +75,7 @@ TEST(connection_write)
>         assert(memcmp(message, buffer, sizeof message) == 0);
>
>         wl_connection_destroy(connection);
> +       close(s[0]);
>         close(s[1]);
>  }
>
> @@ -92,6 +94,7 @@ TEST(connection_data)
>         wl_connection_consume(connection, sizeof message);
>
>         wl_connection_destroy(connection);
> +       close(s[0]);
>         close(s[1]);
>  }
>
> @@ -117,6 +120,7 @@ TEST(connection_queue)
>         assert(memcmp(message, buffer + sizeof message, sizeof message) ==
> 0);
>
>         wl_connection_destroy(connection);
> +       close(s[0]);
>         close(s[1]);
>  }
>
> @@ -147,8 +151,8 @@ setup_marshal_data(struct marshal_data *data)
>  static void
>  release_marshal_data(struct marshal_data *data)
>  {
> -       wl_connection_destroy(data->read_connection);
> -       wl_connection_destroy(data->write_connection);
> +       close(wl_connection_destroy(data->read_connection));
> +       close(wl_connection_destroy(data->write_connection));
>  }
>
>  static void
> --
> 2.1.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to