Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ] tools/iso-tester: add tests for socket shutdown with linger enabled
@ 2026-07-21  9:20 Pauli Virtanen
  2026-07-21 11:18 ` [BlueZ] " bluez.test.bot
  2026-07-21 19:15 ` [PATCH BlueZ] " Luiz Augusto von Dentz
  0 siblings, 2 replies; 3+ messages in thread
From: Pauli Virtanen @ 2026-07-21  9:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen

Add tests with SO_LINGER enabled, to test kernel sock transitions
properly to BT_CLOSED on shutdown.

Unlike L2CAP, ISO sockets don't have a feature to send POLLHUP only
after HCI Disconnect is received, so only SO_LINGER can be used to test
the sequence is shutdown -> Disconnect, HUP -> release, and not
shutdown -> HUP -> release -> Disconnect.

Add tests:

ISO Defer Linger - Success
ISO Connect Linger - Success
---
 tools/iso-tester.c | 68 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/tools/iso-tester.c b/tools/iso-tester.c
index fe27eaaf3..a792a804b 100644
--- a/tools/iso-tester.c
+++ b/tools/iso-tester.c
@@ -478,6 +478,7 @@ struct test_data {
 	bool suspending;
 	struct tx_tstamp_data tx_ts;
 	int seqnum;
+	GThread *thread;
 };
 
 struct iso_client_data {
@@ -522,6 +523,9 @@ struct iso_client_data {
 	 * Used for testing TX timestamping OPT_ID.
 	 */
 	unsigned int repeat_send;
+
+	/* Whether to enable SO_LINGER (for test_connect_wait_close) */
+	bool so_linger;
 };
 
 typedef bool (*iso_defer_accept_t)(struct test_data *data, GIOChannel *io,
@@ -717,6 +721,11 @@ static void test_post_teardown(const void *test_data)
 
 	hciemu_unref(data->hciemu);
 	data->hciemu = NULL;
+
+	if (data->thread) {
+		g_thread_unref(data->thread);
+		data->thread = NULL;
+	}
 }
 
 static void test_data_free(void *test_data)
@@ -1352,6 +1361,19 @@ static const struct iso_client_data connect_ac_1_2_cig_1_2 = {
 	.mconn = true,
 };
 
+static const struct iso_client_data linger_16_2_1 = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.so_linger = true,
+};
+
+static const struct iso_client_data linger_defer_16_2_1 = {
+	.qos = QOS_16_2_1,
+	.expect_err = 0,
+	.defer = true,
+	.so_linger = true,
+};
+
 static const struct iso_client_data bcast_48_1_g = {
 	.qos = QOS_OUT_48_1_g,
 	.expect_err = 0,
@@ -3679,6 +3701,19 @@ static void test_connect2_busy(const void *test_data)
 	setup_connect(data, 0, iso_connect_cb_busy);
 }
 
+static gpointer shutdown_sk_thread_cb(gpointer data)
+{
+	int sk = PTR_TO_UINT(data);
+	struct timespec start, end;
+
+	clock_gettime(CLOCK_MONOTONIC, &start);
+	shutdown(sk, SHUT_RDWR);
+	clock_gettime(CLOCK_MONOTONIC, &end);
+
+	/* Completed before linger timeout? */
+	return UINT_TO_PTR(TS_NSEC(&end) - TS_NSEC(&start) < SEC_NSEC(2));
+}
+
 static gboolean iso_connect_close_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -3688,6 +3723,13 @@ static gboolean iso_connect_close_cb(GIOChannel *io, GIOCondition cond,
 
 	tester_print("Disconnected");
 
+	if (data->thread) {
+		/* Wait for shutdown() to complete, for linger enabled */
+		if (!g_thread_join(data->thread))
+			tester_test_failed();
+		data->thread = NULL;
+	}
+
 	--data->step;
 	if (!data->step)
 		tester_test_passed();
@@ -3737,16 +3779,34 @@ static gboolean iso_connect_wait_close_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
 	struct test_data *data = tester_get_data();
+	const struct iso_client_data *isodata = data->test_data;
 	int sk;
 
 	tester_print("Connected");
 
 	sk = g_io_channel_unix_get_fd(io);
 
+	if (isodata->so_linger) {
+		struct linger val = { .l_onoff = 1, .l_linger = 2 };
+
+		if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &val, sizeof(val))) {
+			tester_warn("Can't set socket option : %s (%d)",
+							strerror(errno), errno);
+			tester_test_failed();
+			return FALSE;
+		}
+	}
+
 	data->io_id[0] = g_io_add_watch(io, G_IO_HUP, iso_connect_close_cb,
 									data);
 
-	shutdown(sk, SHUT_RDWR);
+	if (!isodata->so_linger)
+		shutdown(sk, SHUT_RDWR);
+	else {
+		/* With linger shutdown() blocks, so run in separate thread */
+		data->thread = g_thread_new("close_sk", shutdown_sk_thread_cb,
+							UINT_TO_PTR(sk));
+	}
 
 	return FALSE;
 }
@@ -4160,6 +4220,12 @@ int main(int argc, char *argv[])
 	test_iso("ISO Connect Wait Close - Success", &connect_16_2_1,
 					setup_powered, test_connect_wait_close);
 
+	test_iso("ISO Defer Linger - Success", &linger_16_2_1,
+					setup_powered, test_connect_wait_close);
+
+	test_iso("ISO Connect Linger - Success", &linger_defer_16_2_1,
+					setup_powered, test_connect_wait_close);
+
 	test_iso("ISO Connect Suspend - Success", &connect_suspend,
 							setup_powered,
 							test_connect_suspend);
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* RE: [BlueZ] tools/iso-tester: add tests for socket shutdown with linger enabled
  2026-07-21  9:20 [PATCH BlueZ] tools/iso-tester: add tests for socket shutdown with linger enabled Pauli Virtanen
@ 2026-07-21 11:18 ` bluez.test.bot
  2026-07-21 19:15 ` [PATCH BlueZ] " Luiz Augusto von Dentz
  1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-07-21 11:18 UTC (permalink / raw)
  To: linux-bluetooth, pav

[-- Attachment #1: Type: text/plain, Size: 538 bytes --]

This is an automated email and please do not reply to this email.

Dear Submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.

----- Output -----

error: patch failed: tools/iso-tester.c:717
error: tools/iso-tester.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch

Please resolve the issue and submit the patches again.


---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH BlueZ] tools/iso-tester: add tests for socket shutdown with linger enabled
  2026-07-21  9:20 [PATCH BlueZ] tools/iso-tester: add tests for socket shutdown with linger enabled Pauli Virtanen
  2026-07-21 11:18 ` [BlueZ] " bluez.test.bot
@ 2026-07-21 19:15 ` Luiz Augusto von Dentz
  1 sibling, 0 replies; 3+ messages in thread
From: Luiz Augusto von Dentz @ 2026-07-21 19:15 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: linux-bluetooth

Hi Pauli,

On Tue, Jul 21, 2026 at 5:20 AM Pauli Virtanen <pav@iki.fi> wrote:
>
> Add tests with SO_LINGER enabled, to test kernel sock transitions
> properly to BT_CLOSED on shutdown.
>
> Unlike L2CAP, ISO sockets don't have a feature to send POLLHUP only
> after HCI Disconnect is received, so only SO_LINGER can be used to test
> the sequence is shutdown -> Disconnect, HUP -> release, and not
> shutdown -> HUP -> release -> Disconnect.
>
> Add tests:
>
> ISO Defer Linger - Success
> ISO Connect Linger - Success
> ---
>  tools/iso-tester.c | 68 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 67 insertions(+), 1 deletion(-)
>
> diff --git a/tools/iso-tester.c b/tools/iso-tester.c
> index fe27eaaf3..a792a804b 100644
> --- a/tools/iso-tester.c
> +++ b/tools/iso-tester.c
> @@ -478,6 +478,7 @@ struct test_data {
>         bool suspending;
>         struct tx_tstamp_data tx_ts;
>         int seqnum;
> +       GThread *thread;

I don't think this is a good idea, most of our userspace code isn't
thread-safe, so I'd prefer we keep it that way and perhaps handle this
with some async I/O or something else.

>  };
>
>  struct iso_client_data {
> @@ -522,6 +523,9 @@ struct iso_client_data {
>          * Used for testing TX timestamping OPT_ID.
>          */
>         unsigned int repeat_send;
> +
> +       /* Whether to enable SO_LINGER (for test_connect_wait_close) */
> +       bool so_linger;
>  };
>
>  typedef bool (*iso_defer_accept_t)(struct test_data *data, GIOChannel *io,
> @@ -717,6 +721,11 @@ static void test_post_teardown(const void *test_data)
>
>         hciemu_unref(data->hciemu);
>         data->hciemu = NULL;
> +
> +       if (data->thread) {
> +               g_thread_unref(data->thread);
> +               data->thread = NULL;
> +       }
>  }
>
>  static void test_data_free(void *test_data)
> @@ -1352,6 +1361,19 @@ static const struct iso_client_data connect_ac_1_2_cig_1_2 = {
>         .mconn = true,
>  };
>
> +static const struct iso_client_data linger_16_2_1 = {
> +       .qos = QOS_16_2_1,
> +       .expect_err = 0,
> +       .so_linger = true,
> +};
> +
> +static const struct iso_client_data linger_defer_16_2_1 = {
> +       .qos = QOS_16_2_1,
> +       .expect_err = 0,
> +       .defer = true,
> +       .so_linger = true,
> +};
> +
>  static const struct iso_client_data bcast_48_1_g = {
>         .qos = QOS_OUT_48_1_g,
>         .expect_err = 0,
> @@ -3679,6 +3701,19 @@ static void test_connect2_busy(const void *test_data)
>         setup_connect(data, 0, iso_connect_cb_busy);
>  }
>
> +static gpointer shutdown_sk_thread_cb(gpointer data)
> +{
> +       int sk = PTR_TO_UINT(data);
> +       struct timespec start, end;
> +
> +       clock_gettime(CLOCK_MONOTONIC, &start);
> +       shutdown(sk, SHUT_RDWR);
> +       clock_gettime(CLOCK_MONOTONIC, &end);
> +
> +       /* Completed before linger timeout? */
> +       return UINT_TO_PTR(TS_NSEC(&end) - TS_NSEC(&start) < SEC_NSEC(2));
> +}
> +
>  static gboolean iso_connect_close_cb(GIOChannel *io, GIOCondition cond,
>                                                         gpointer user_data)
>  {
> @@ -3688,6 +3723,13 @@ static gboolean iso_connect_close_cb(GIOChannel *io, GIOCondition cond,
>
>         tester_print("Disconnected");
>
> +       if (data->thread) {
> +               /* Wait for shutdown() to complete, for linger enabled */
> +               if (!g_thread_join(data->thread))
> +                       tester_test_failed();
> +               data->thread = NULL;
> +       }
> +
>         --data->step;
>         if (!data->step)
>                 tester_test_passed();
> @@ -3737,16 +3779,34 @@ static gboolean iso_connect_wait_close_cb(GIOChannel *io, GIOCondition cond,
>                                                         gpointer user_data)
>  {
>         struct test_data *data = tester_get_data();
> +       const struct iso_client_data *isodata = data->test_data;
>         int sk;
>
>         tester_print("Connected");
>
>         sk = g_io_channel_unix_get_fd(io);
>
> +       if (isodata->so_linger) {
> +               struct linger val = { .l_onoff = 1, .l_linger = 2 };
> +
> +               if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &val, sizeof(val))) {
> +                       tester_warn("Can't set socket option : %s (%d)",
> +                                                       strerror(errno), errno);
> +                       tester_test_failed();
> +                       return FALSE;
> +               }
> +       }
> +
>         data->io_id[0] = g_io_add_watch(io, G_IO_HUP, iso_connect_close_cb,
>                                                                         data);
>
> -       shutdown(sk, SHUT_RDWR);
> +       if (!isodata->so_linger)
> +               shutdown(sk, SHUT_RDWR);
> +       else {
> +               /* With linger shutdown() blocks, so run in separate thread */
> +               data->thread = g_thread_new("close_sk", shutdown_sk_thread_cb,
> +                                                       UINT_TO_PTR(sk));
> +       }
>
>         return FALSE;
>  }
> @@ -4160,6 +4220,12 @@ int main(int argc, char *argv[])
>         test_iso("ISO Connect Wait Close - Success", &connect_16_2_1,
>                                         setup_powered, test_connect_wait_close);
>
> +       test_iso("ISO Defer Linger - Success", &linger_16_2_1,
> +                                       setup_powered, test_connect_wait_close);
> +
> +       test_iso("ISO Connect Linger - Success", &linger_defer_16_2_1,
> +                                       setup_powered, test_connect_wait_close);
> +
>         test_iso("ISO Connect Suspend - Success", &connect_suspend,
>                                                         setup_powered,
>                                                         test_connect_suspend);
> --
> 2.55.0
>
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-21 19:16 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21  9:20 [PATCH BlueZ] tools/iso-tester: add tests for socket shutdown with linger enabled Pauli Virtanen
2026-07-21 11:18 ` [BlueZ] " bluez.test.bot
2026-07-21 19:15 ` [PATCH BlueZ] " Luiz Augusto von Dentz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox