diff mbox

[v2,lttng-tools,master,2.10-rc] Introduce "--blocking-timeout" channel parameter

Message ID 1495865859-25810-1-git-send-email-mathieu.desnoyers@efficios.com
State Accepted, archived
Delegated to: Jérémie Galarneau
Headers show

Commit Message

Mathieu Desnoyers May 27, 2017, 6:17 a.m. UTC
Introduce the blocking timeout channel parameter to control blocking
behavior for lttng-ust buffers. It only affects applications launched
with the LTTNG_UST_ALLOW_BLOCKING environment variable.

The blocking timeout parameter expects:

- 0 (default) which does not block,
- a timeout value in usec,
- -1 (block forever).

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
---
 configure.ac                                |  4 +++
 doc/man/lttng-enable-channel.1.txt          | 14 +++++++-
 include/lttng/channel-internal.h            |  1 +
 include/lttng/channel.h                     |  6 ++++
 src/bin/lttng-sessiond/channel.c            | 17 ++++++++++
 src/bin/lttng-sessiond/cmd.c                |  3 ++
 src/bin/lttng-sessiond/consumer.c           |  2 ++
 src/bin/lttng-sessiond/consumer.h           |  1 +
 src/bin/lttng-sessiond/lttng-ust-abi.h      |  7 +++-
 src/bin/lttng-sessiond/lttng-ust-ctl.h      |  1 +
 src/bin/lttng-sessiond/trace-ust.c          |  2 ++
 src/bin/lttng-sessiond/ust-app.c            |  4 +++
 src/bin/lttng-sessiond/ust-consumer.c       |  1 +
 src/bin/lttng/commands/enable_channels.c    | 52 +++++++++++++++++++++++++++++
 src/bin/lttng/commands/list.c               |  9 +++++
 src/common/config/config-session-abi.h      |  1 +
 src/common/config/session-config.c          |  1 +
 src/common/config/session.xsd               | 13 ++++++++
 src/common/defaults.h                       |  4 +++
 src/common/mi-lttng-3.0.xsd                 | 14 ++++++++
 src/common/mi-lttng.c                       | 15 +++++++++
 src/common/sessiond-comm/sessiond-comm.h    |  1 +
 src/common/ust-consumer/ust-consumer.c      |  1 +
 src/lib/lttng-ctl/lttng-ctl.c               | 44 ++++++++++++++++++++++++
 tests/regression/ust/blocking/test_blocking | 49 +++++++++++++++------------
 25 files changed, 244 insertions(+), 23 deletions(-)

Comments

Jérémie Galarneau June 12, 2017, 9:28 p.m. UTC | #1
On 27 May 2017 at 02:17, Mathieu Desnoyers
<mathieu.desnoyers at efficios.com> wrote:
> Introduce the blocking timeout channel parameter to control blocking
> behavior for lttng-ust buffers. It only affects applications launched
> with the LTTNG_UST_ALLOW_BLOCKING environment variable.
>
> The blocking timeout parameter expects:
>
> - 0 (default) which does not block,
> - a timeout value in usec,
> - -1 (block forever).
>
> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
> ---
>  configure.ac                                |  4 +++
>  doc/man/lttng-enable-channel.1.txt          | 14 +++++++-
>  include/lttng/channel-internal.h            |  1 +
>  include/lttng/channel.h                     |  6 ++++
>  src/bin/lttng-sessiond/channel.c            | 17 ++++++++++
>  src/bin/lttng-sessiond/cmd.c                |  3 ++
>  src/bin/lttng-sessiond/consumer.c           |  2 ++
>  src/bin/lttng-sessiond/consumer.h           |  1 +
>  src/bin/lttng-sessiond/lttng-ust-abi.h      |  7 +++-
>  src/bin/lttng-sessiond/lttng-ust-ctl.h      |  1 +
>  src/bin/lttng-sessiond/trace-ust.c          |  2 ++
>  src/bin/lttng-sessiond/ust-app.c            |  4 +++
>  src/bin/lttng-sessiond/ust-consumer.c       |  1 +
>  src/bin/lttng/commands/enable_channels.c    | 52 +++++++++++++++++++++++++++++
>  src/bin/lttng/commands/list.c               |  9 +++++
>  src/common/config/config-session-abi.h      |  1 +
>  src/common/config/session-config.c          |  1 +
>  src/common/config/session.xsd               | 13 ++++++++
>  src/common/defaults.h                       |  4 +++
>  src/common/mi-lttng-3.0.xsd                 | 14 ++++++++
>  src/common/mi-lttng.c                       | 15 +++++++++
>  src/common/sessiond-comm/sessiond-comm.h    |  1 +
>  src/common/ust-consumer/ust-consumer.c      |  1 +
>  src/lib/lttng-ctl/lttng-ctl.c               | 44 ++++++++++++++++++++++++
>  tests/regression/ust/blocking/test_blocking | 49 +++++++++++++++------------
>  25 files changed, 244 insertions(+), 23 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index 9239e3b..19f2d67 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -246,6 +246,7 @@ m4_define([_DEFAULT_CHANNEL_SWITCH_TIMER], [0])
>  m4_define([_DEFAULT_CHANNEL_LIVE_TIMER], [0])
>  m4_define([_DEFAULT_CHANNEL_READ_TIMER], [200000])
>  m4_define([_DEFAULT_CHANNEL_MONITOR_TIMER], [1000000])
> +m4_define([_DEFAULT_CHANNEL_BLOCKING_TIMEOUT], [0])
>  _AC_DEFINE_AND_SUBST([DEFAULT_AGENT_TCP_PORT], [5345])
>  _AC_DEFINE_AND_SUBST([DEFAULT_APP_SOCKET_RW_TIMEOUT], [5])
>  _AC_DEFINE_AND_SUBST([DEFAULT_CHANNEL_SUBBUF_SIZE], [_DEFAULT_CHANNEL_SUBBUF_SIZE])
> @@ -257,6 +258,7 @@ _AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM], [_DEFAULT_CHANNEL_SUBB
>  _AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE], [1048576])
>  _AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER], [_DEFAULT_CHANNEL_SWITCH_TIMER])
>  _AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER], [_DEFAULT_CHANNEL_MONITOR_TIMER])
> +_AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT], [_DEFAULT_CHANNEL_BLOCKING_TIMEOUT])
>  _AC_DEFINE_AND_SUBST([DEFAULT_LTTNG_LIVE_TIMER], [1000000])
>  _AC_DEFINE_AND_SUBST([DEFAULT_METADATA_CACHE_SIZE], [4096])
>  _AC_DEFINE_AND_SUBST([DEFAULT_METADATA_READ_TIMER], [0])
> @@ -268,12 +270,14 @@ _AC_DEFINE_AND_SUBST([DEFAULT_NETWORK_DATA_PORT], [5343])
>  _AC_DEFINE_AND_SUBST([DEFAULT_NETWORK_VIEWER_PORT], [5344])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_LIVE_TIMER], [_DEFAULT_CHANNEL_LIVE_TIMER])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_READ_TIMER], [0])
> +_AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT], [0])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM], [_DEFAULT_CHANNEL_SUBBUF_NUM])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_SUBBUF_SIZE], [_DEFAULT_CHANNEL_SUBBUF_SIZE])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER], [_DEFAULT_CHANNEL_SWITCH_TIMER])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER], [_DEFAULT_CHANNEL_MONITOR_TIMER])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_LIVE_TIMER], [_DEFAULT_CHANNEL_LIVE_TIMER])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_READ_TIMER], [0])
> +_AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT], [0])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM], [_DEFAULT_CHANNEL_SUBBUF_NUM])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_SUBBUF_SIZE], [524288])
>  _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER], [_DEFAULT_CHANNEL_SWITCH_TIMER])
> diff --git a/doc/man/lttng-enable-channel.1.txt b/doc/man/lttng-enable-channel.1.txt
> index f9b0b1f..d66d2fb 100644
> --- a/doc/man/lttng-enable-channel.1.txt
> +++ b/doc/man/lttng-enable-channel.1.txt
> @@ -26,6 +26,7 @@ Create a user space channel:
>        [option:--overwrite] [option:--buffers-pid]
>        [option:--subbuf-size='SIZE'] [option:--num-subbuf='COUNT']
>        [option:--switch-timer='PERIODUS'] [option:--read-timer='PERIODUS']
> +      [option:--blocking-timeout='TIMEOUTUS']
>        [option:--tracefile-size='SIZE'] [option:--tracefile-count='COUNT']
>        [option:--session='SESSION'] 'CHANNEL'
>
> @@ -358,6 +359,16 @@ Default values:
>  * option:--kernel option: {default_kernel_channel_switch_timer}
>  * `metadata` channel: {default_metadata_switch_timer}
>
> +Timeouts
> +~~~~~~~~
> +option:--blocking-timeout:
> +    Set the channel's blocking timeout value to 'TIMEOUTUS' µs. 0
> +    (default) does not block. -1 blocks forever until room is
> +    available in the buffer to write the event. Positive
> +    values are a timeout bounding the maximum blocking time
> +    when trying to write into the buffer. Note that this option
> +    only affects applications launched with the
> +    LTTNG_UST_ALLOW_BLOCKING environment variable set.
>
>  include::common-cmd-help-options.txt[]
>
> @@ -385,4 +396,5 @@ include::common-cmd-footer.txt[]
>  SEE ALSO
>  --------
>  man:lttng-disable-channel(1),
> -man:lttng(1)
> +man:lttng(1),
> +man:lttng-ust(3)
> diff --git a/include/lttng/channel-internal.h b/include/lttng/channel-internal.h
> index d78a720..53171f4 100644
> --- a/include/lttng/channel-internal.h
> +++ b/include/lttng/channel-internal.h
> @@ -22,6 +22,7 @@ struct lttng_channel_extended {
>         uint64_t discarded_events;
>         uint64_t lost_packets;
>         uint64_t monitor_timer_interval;
> +       int64_t blocking_timeout;
>  } LTTNG_PACKED;
>
>  #endif /* LTTNG_CHANNEL_INTERNAL_H */
> diff --git a/include/lttng/channel.h b/include/lttng/channel.h
> index e20ed4f..4e61a61 100644
> --- a/include/lttng/channel.h
> +++ b/include/lttng/channel.h
> @@ -138,6 +138,12 @@ extern int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan,
>  extern int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan,
>                 uint64_t monitor_timer_interval);
>
> +extern int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
> +               int64_t *blocking_timeout);
> +
> +extern int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
> +               int64_t blocking_timeout);
> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/src/bin/lttng-sessiond/channel.c b/src/bin/lttng-sessiond/channel.c
> index 8a88ecc..5aa0cd8 100644
> --- a/src/bin/lttng-sessiond/channel.c
> +++ b/src/bin/lttng-sessiond/channel.c
> @@ -72,6 +72,7 @@ struct lttng_channel *channel_new_default_attr(int dom,
>                 chan->attr.switch_timer_interval = DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER;
>                 chan->attr.read_timer_interval = DEFAULT_KERNEL_CHANNEL_READ_TIMER;
>                 chan->attr.live_timer_interval = DEFAULT_KERNEL_CHANNEL_LIVE_TIMER;
> +               extended_attr->blocking_timeout = DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
>                 extended_attr->monitor_timer_interval =
>                         DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
>                 break;
> @@ -97,6 +98,7 @@ common_ust:
>                                 DEFAULT_UST_UID_CHANNEL_READ_TIMER;
>                         chan->attr.live_timer_interval =
>                                 DEFAULT_UST_UID_CHANNEL_LIVE_TIMER;
> +                       extended_attr->blocking_timeout = DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
>                         extended_attr->monitor_timer_interval =
>                                 DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
>                         break;
> @@ -111,6 +113,7 @@ common_ust:
>                                 DEFAULT_UST_PID_CHANNEL_READ_TIMER;
>                         chan->attr.live_timer_interval =
>                                 DEFAULT_UST_PID_CHANNEL_LIVE_TIMER;
> +                       extended_attr->blocking_timeout = DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
>                         extended_attr->monitor_timer_interval =
>                                 DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
>                         break;
> @@ -217,6 +220,15 @@ static int channel_validate(struct lttng_channel *attr)
>         return 0;
>  }
>
> +static int channel_validate_kernel(struct lttng_channel *attr)
> +{
> +       /* Kernel channels do not support blocking timeout. */
> +       if (((struct lttng_channel_extended *)attr->attr.extended.ptr)->blocking_timeout) {
> +               return -1;
> +       }
> +       return 0;
> +}
> +
>  /*
>   * Create kernel channel of the kernel session and notify kernel thread.
>   */
> @@ -258,6 +270,11 @@ int channel_kernel_create(struct ltt_kernel_session *ksession,
>                 goto error;
>         }
>
> +       if (channel_validate_kernel(attr) < 0) {
> +               ret = LTTNG_ERR_INVALID;
> +               goto error;
> +       }
> +
>         /* Channel not found, creating it */
>         ret = kernel_create_channel(ksession, attr);
>         if (ret < 0) {
> diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c
> index dea5ab2..73a309d 100644
> --- a/src/bin/lttng-sessiond/cmd.c
> +++ b/src/bin/lttng-sessiond/cmd.c
> @@ -277,6 +277,7 @@ static ssize_t list_lttng_channels(enum lttng_domain_type domain,
>                                 chan_exts[i].lost_packets = lost_packets;
>                                 chan_exts[i].monitor_timer_interval =
>                                                 extended->monitor_timer_interval;
> +                               chan_exts[i].blocking_timeout = 0;
>                                 i++;
>                         }
>                 }
> @@ -324,6 +325,8 @@ static ssize_t list_lttng_channels(enum lttng_domain_type domain,
>
>                         chan_exts[i].monitor_timer_interval =
>                                         uchan->monitor_timer_interval;
> +                       chan_exts[i].blocking_timeout =
> +                               uchan->attr.u.s.blocking_timeout;
>
>                         ret = get_ust_runtime_stats(session, uchan,
>                                         &discarded_events, &lost_packets);
> diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c
> index 4a7287b..33ccfe2 100644
> --- a/src/bin/lttng-sessiond/consumer.c
> +++ b/src/bin/lttng-sessiond/consumer.c
> @@ -822,6 +822,7 @@ void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg,
>                 uint64_t session_id_per_pid,
>                 unsigned int monitor,
>                 uint32_t ust_app_uid,
> +               int64_t blocking_timeout,
>                 const char *root_shm_path,
>                 const char *shm_path)
>  {
> @@ -851,6 +852,7 @@ void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg,
>         msg->u.ask_channel.tracefile_count = tracefile_count;
>         msg->u.ask_channel.monitor = monitor;
>         msg->u.ask_channel.ust_app_uid = ust_app_uid;
> +       msg->u.ask_channel.blocking_timeout = blocking_timeout;
>
>         memcpy(msg->u.ask_channel.uuid, uuid, sizeof(msg->u.ask_channel.uuid));
>
> diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h
> index 77bc2b1..b8d5630 100644
> --- a/src/bin/lttng-sessiond/consumer.h
> +++ b/src/bin/lttng-sessiond/consumer.h
> @@ -256,6 +256,7 @@ void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg,
>                 uint64_t session_id_per_pid,
>                 unsigned int monitor,
>                 uint32_t ust_app_uid,
> +               int64_t blocking_timeout,
>                 const char *root_shm_path,
>                 const char *shm_path);
>  void consumer_init_stream_comm_msg(struct lttcomm_consumer_msg *msg,
> diff --git a/src/bin/lttng-sessiond/lttng-ust-abi.h b/src/bin/lttng-sessiond/lttng-ust-abi.h
> index 972de0c..687eb0b 100644
> --- a/src/bin/lttng-sessiond/lttng-ust-abi.h
> +++ b/src/bin/lttng-sessiond/lttng-ust-abi.h
> @@ -181,7 +181,12 @@ struct lttng_ust_channel_attr {
>         unsigned int switch_timer_interval;     /* usec */
>         unsigned int read_timer_interval;       /* usec */
>         enum lttng_ust_output output;           /* splice, mmap */
> -       char padding[LTTNG_UST_CHANNEL_ATTR_PADDING];
> +       union {
> +               struct {
> +                       int64_t blocking_timeout;       /* Retry timeout (usec) */
> +               } s;
> +               char padding[LTTNG_UST_CHANNEL_ATTR_PADDING];
> +       } u;
>  } LTTNG_PACKED;
>
>  #define LTTNG_UST_TRACEPOINT_ITER_PADDING      16
> diff --git a/src/bin/lttng-sessiond/lttng-ust-ctl.h b/src/bin/lttng-sessiond/lttng-ust-ctl.h
> index cba0e27..1d67e85 100644
> --- a/src/bin/lttng-sessiond/lttng-ust-ctl.h
> +++ b/src/bin/lttng-sessiond/lttng-ust-ctl.h
> @@ -53,6 +53,7 @@ struct ustctl_consumer_channel_attr {
>         enum lttng_ust_output output;           /* splice, mmap */
>         uint32_t chan_id;           /* channel ID */
>         unsigned char uuid[LTTNG_UST_UUID_LEN]; /* Trace session unique ID */
> +       int64_t blocking_timeout;                       /* Retry timeout (usec) */
>  } LTTNG_PACKED;
>
>  /*
> diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c
> index 314c21e..bcb04fe 100644
> --- a/src/bin/lttng-sessiond/trace-ust.c
> +++ b/src/bin/lttng-sessiond/trace-ust.c
> @@ -358,6 +358,8 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan,
>         luc->attr.output = (enum lttng_ust_output) chan->attr.output;
>         luc->monitor_timer_interval = ((struct lttng_channel_extended *)
>                         chan->attr.extended.ptr)->monitor_timer_interval;
> +       luc->attr.u.s.blocking_timeout = ((struct lttng_channel_extended *)
> +                       chan->attr.extended.ptr)->blocking_timeout;
>
>         /* Translate to UST output enum */
>         switch (luc->attr.output) {
> diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c
> index 8176d4d..df46f42 100644
> --- a/src/bin/lttng-sessiond/ust-app.c
> +++ b/src/bin/lttng-sessiond/ust-app.c
> @@ -92,6 +92,7 @@ static void copy_channel_attr_to_ustctl(
>         attr->switch_timer_interval = uattr->switch_timer_interval;
>         attr->read_timer_interval = uattr->read_timer_interval;
>         attr->output = uattr->output;
> +       attr->blocking_timeout = uattr->u.s.blocking_timeout;
>  }
>
>  /*
> @@ -1035,6 +1036,7 @@ struct ust_app_channel *alloc_ust_app_channel(char *name,
>                 ua_chan->attr.switch_timer_interval = attr->switch_timer_interval;
>                 ua_chan->attr.read_timer_interval = attr->read_timer_interval;
>                 ua_chan->attr.output = attr->output;
> +               ua_chan->attr.blocking_timeout = attr->u.s.blocking_timeout;
>         }
>         /* By default, the channel is a per cpu channel. */
>         ua_chan->attr.type = LTTNG_UST_CHAN_PER_CPU;
> @@ -1798,6 +1800,8 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan,
>         ua_chan->attr.read_timer_interval = uchan->attr.read_timer_interval;
>         ua_chan->monitor_timer_interval = uchan->monitor_timer_interval;
>         ua_chan->attr.output = uchan->attr.output;
> +       ua_chan->attr.blocking_timeout = uchan->attr.u.s.blocking_timeout;
> +
>         /*
>          * Note that the attribute channel type is not set since the channel on the
>          * tracing registry side does not have this information.
> diff --git a/src/bin/lttng-sessiond/ust-consumer.c b/src/bin/lttng-sessiond/ust-consumer.c
> index fe2c8f4..43bf261 100644
> --- a/src/bin/lttng-sessiond/ust-consumer.c
> +++ b/src/bin/lttng-sessiond/ust-consumer.c
> @@ -192,6 +192,7 @@ static int ask_channel_creation(struct ust_app_session *ua_sess,
>                         ua_sess->id,
>                         ua_sess->output_traces,
>                         ua_sess->uid,
> +                       ua_chan->attr.blocking_timeout,
>                         root_shm_path, shm_path);
>
>         health_code_update();
> diff --git a/src/bin/lttng/commands/enable_channels.c b/src/bin/lttng/commands/enable_channels.c
> index 22331ce..9d71720 100644
> --- a/src/bin/lttng/commands/enable_channels.c
> +++ b/src/bin/lttng/commands/enable_channels.c
> @@ -48,6 +48,10 @@ static struct {
>         bool set;
>         uint32_t interval;
>  } opt_monitor_timer;
> +static struct {
> +       bool set;
> +       int64_t value;
> +} opt_blocking_timeout;
>
>  static struct mi_writer *writer;
>
> @@ -70,6 +74,7 @@ enum {
>         OPT_LIST_OPTIONS,
>         OPT_TRACEFILE_SIZE,
>         OPT_TRACEFILE_COUNT,
> +       OPT_BLOCKING_TIMEOUT,
>  };
>
>  static struct lttng_handle *handle;
> @@ -97,6 +102,7 @@ static struct poptOption long_options[] = {
>         {"buffers-global", 0,   POPT_ARG_VAL, &opt_buffer_global, 1, 0, 0},
>         {"tracefile-size", 'C',   POPT_ARG_INT, 0, OPT_TRACEFILE_SIZE, 0, 0},
>         {"tracefile-count", 'W',   POPT_ARG_INT, 0, OPT_TRACEFILE_COUNT, 0, 0},
> +       {"blocking-timeout",     0,   POPT_ARG_INT, 0, OPT_BLOCKING_TIMEOUT, 0, 0},
>         {0, 0, 0, 0, 0, 0, 0}
>  };
>
> @@ -151,6 +157,15 @@ static int enable_channel(char *session_name)
>
>         memset(&dom, 0, sizeof(dom));
>
> +       /* Validate options. */
> +       if (opt_kernel) {
> +               if (opt_blocking_timeout.set) {
> +                       ERR("Retry timeout option not supported for kernel domain (-k)");
> +                       ret = CMD_ERROR;
> +                       goto error;
> +               }
> +       }
> +
>         /* Create lttng domain */
>         if (opt_kernel) {
>                 dom.type = LTTNG_DOMAIN_KERNEL;
> @@ -262,6 +277,15 @@ static int enable_channel(char *session_name)
>                                 goto error;
>                         }
>                 }
> +               if (opt_blocking_timeout.set) {
> +                       ret = lttng_channel_set_blocking_timeout(channel,
> +                                       opt_blocking_timeout.value);
> +                       if (ret) {
> +                               ERR("Failed to set the channel's blocking timeout");
> +                               error = 1;
> +                               goto error;
> +                       }
> +               }
>
>                 DBG("Enabling channel %s", channel_name);
>
> @@ -530,6 +554,34 @@ int cmd_enable_channels(int argc, const char **argv)
>                         DBG("Channel monitor timer interval set to %d", opt_monitor_timer.interval);
>                         break;
>                 }
> +               case OPT_BLOCKING_TIMEOUT:
> +               {
> +                       long long v;    /* in usec */
> +                       long long v_msec;
> +
> +                       errno = 0;
> +                       opt_arg = poptGetOptArg(pc);
> +                       v = strtoll(opt_arg, NULL, 0);
> +                       if (errno != 0 || (!isdigit(opt_arg[0]) && opt_arg[0] != '-')
> +                                       || v < -1) {
> +                               ERR("Wrong value in --blocking_timeout parameter: %s", opt_arg);
> +                               ret = CMD_ERROR;
> +                               goto end;
> +                       }
> +                       if (v >= 0) {
> +                               v_msec = v / 1000;
> +                               if (v_msec != (int32_t) v_msec) {
> +                                       ERR("32-bit milliseconds overflow in --blocking_timeout parameter: %s", opt_arg);
> +                                       ret = CMD_ERROR;
> +                                       goto end;
> +                               }
> +                       }
> +                       opt_blocking_timeout.value = (int64_t) v;
> +                       opt_blocking_timeout.set = true;
> +                       DBG("Channel blocking timeout set to %" PRId64 " (µs)",
> +                               opt_blocking_timeout.value);
> +                       break;
> +               }
>                 case OPT_USERSPACE:
>                         opt_userspace = 1;
>                         break;
> diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c
> index 1315783..942e4a4 100644
> --- a/src/bin/lttng/commands/list.c
> +++ b/src/bin/lttng/commands/list.c
> @@ -1173,6 +1173,7 @@ static void print_channel(struct lttng_channel *channel)
>  {
>         int ret;
>         uint64_t discarded_events, lost_packets, monitor_timer_interval;
> +       int64_t blocking_timeout;
>
>         ret = lttng_channel_get_discarded_event_count(channel,
>                         &discarded_events);
> @@ -1195,6 +1196,13 @@ static void print_channel(struct lttng_channel *channel)
>                 return;
>         }
>
> +       ret = lttng_channel_get_blocking_timeout(channel,
> +                       &blocking_timeout);
> +       if (ret) {
> +               ERR("Failed to retrieve blocking timeout of channel");
> +               return;
> +       }
> +
>         MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
>
>         MSG("%sAttributes:", indent4);
> @@ -1204,6 +1212,7 @@ static void print_channel(struct lttng_channel *channel)
>         MSG("%sswitch timer interval: %u", indent6, channel->attr.switch_timer_interval);
>         MSG("%sread timer interval: %u", indent6, channel->attr.read_timer_interval);
>         MSG("%smonitor timer interval: %" PRIu64, indent6, monitor_timer_interval);
> +       MSG("%sblocking timeout (µs): %" PRId64, indent6, blocking_timeout);
>         MSG("%strace file count: %" PRIu64, indent6, channel->attr.tracefile_count);
>         MSG("%strace file size (bytes): %" PRIu64, indent6, channel->attr.tracefile_size);
>         MSG("%sdiscarded events: %" PRIu64, indent6, discarded_events);
> diff --git a/src/common/config/config-session-abi.h b/src/common/config/config-session-abi.h
> index 2faa354..5f91109 100644
> --- a/src/common/config/config-session-abi.h
> +++ b/src/common/config/config-session-abi.h
> @@ -42,6 +42,7 @@ extern const char * const config_element_num_subbuf;
>  extern const char * const config_element_switch_timer_interval;
>  extern const char * const config_element_read_timer_interval;
>  extern const char * const config_element_monitor_timer_interval;
> +extern const char * const config_element_blocking_timeout;
>  extern const char * const config_element_output;
>  extern const char * const config_element_output_type;
>  extern const char * const config_element_tracefile_size;
> diff --git a/src/common/config/session-config.c b/src/common/config/session-config.c
> index 69b62d7..a629312 100644
> --- a/src/common/config/session-config.c
> +++ b/src/common/config/session-config.c
> @@ -92,6 +92,7 @@ const char * const config_element_num_subbuf = "subbuffer_count";
>  const char * const config_element_switch_timer_interval = "switch_timer_interval";
>  const char * const config_element_read_timer_interval = "read_timer_interval";
>  const char * const config_element_monitor_timer_interval = "monitor_timer_interval";
> +const char * const config_element_blocking_timeout = "blocking_timeout";
>  const char * const config_element_output = "output";
>  const char * const config_element_output_type = "output_type";
>  const char * const config_element_tracefile_size = "tracefile_size";
> diff --git a/src/common/config/session.xsd b/src/common/config/session.xsd
> index 550fea0..6efdc43 100644
> --- a/src/common/config/session.xsd
> +++ b/src/common/config/session.xsd
> @@ -43,6 +43,18 @@ elementFormDefault="qualified" version="2.8">
>         </xs:restriction>
>  </xs:simpleType>
>
> +<!--
> +Maps to the range allowed for blocking timeout: -1 (block forever),
> +0 (do not block), positive integer value (blocking time in usec) limited
> +by its signed 32-bit representation when converted to msec.
> +-->
> +<xs:simpleType name="blocking_timeout_type">
> +       <xs:restriction base="xs:integer">
> +               <xs:minInclusive value="-1" />
> +               <xs:maxInclusive value="2147483648000" />
> +       </xs:restriction>
> +</xs:simpleType>
> +
>  <xs:simpleType name="channel_overwrite_mode_type">
>         <xs:restriction base="xs:string">
>                 <xs:enumeration value="DISCARD"/>
> @@ -186,6 +198,7 @@ elementFormDefault="qualified" version="2.8">
>                 <xs:element name="subbuffer_count" type="uint64_type" default="4" minOccurs="0"/>
>                 <xs:element name="switch_timer_interval" type="uint32_type" default="0" minOccurs="0"/>  <!-- usec -->
>                 <xs:element name="read_timer_interval" type="uint32_type"/>  <!-- usec -->
> +               <xs:element name="blocking_timeout" type="blocking_timeout_type" default="0" minOccurs="0" /> <!-- usec -->
>                 <xs:element name="output_type" type="event_output_type"/>
>                 <xs:element name="tracefile_size" type="uint64_type" default="0" minOccurs="0"/> <!-- bytes -->
>                 <xs:element name="tracefile_count" type="uint64_type" default="0" minOccurs="0"/>
> diff --git a/src/common/defaults.h b/src/common/defaults.h
> index e0d0d86..b810302 100644
> --- a/src/common/defaults.h
> +++ b/src/common/defaults.h
> @@ -221,6 +221,7 @@
>  #define DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER   CONFIG_DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER
>  #define DEFAULT_KERNEL_CHANNEL_READ_TIMER      CONFIG_DEFAULT_KERNEL_CHANNEL_READ_TIMER
>  #define DEFAULT_KERNEL_CHANNEL_LIVE_TIMER      CONFIG_DEFAULT_KERNEL_CHANNEL_LIVE_TIMER
> +#define DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT        CONFIG_DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT
>
>  /* User space defaults */
>
> @@ -244,6 +245,9 @@
>  #define DEFAULT_UST_PID_CHANNEL_READ_TIMER      CONFIG_DEFAULT_UST_PID_CHANNEL_READ_TIMER
>  #define DEFAULT_UST_UID_CHANNEL_READ_TIMER      CONFIG_DEFAULT_UST_UID_CHANNEL_READ_TIMER
>
> +#define DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT       CONFIG_DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT
> +#define DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT       CONFIG_DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT
> +
>  /*
>   * Default timeout value for the sem_timedwait() call. Blocking forever is not
>   * wanted so a timeout is used to control the data flow and not freeze the
> diff --git a/src/common/mi-lttng-3.0.xsd b/src/common/mi-lttng-3.0.xsd
> index 56b65a3..8b2e453 100644
> --- a/src/common/mi-lttng-3.0.xsd
> +++ b/src/common/mi-lttng-3.0.xsd
> @@ -43,6 +43,19 @@ THE SOFTWARE.
>                 </xs:restriction>
>         </xs:simpleType>
>
> +       <!--
> +       Maps to the range allowed for blocking timeout: -1 (block
> +       forever), 0 (do not block), positive integer value (blocking
> +       time in usec) limited by its signed 32-bit representation when
> +       converted to msec.
> +       -->
> +       <xs:simpleType name="blocking_timeout_type">
> +               <xs:restriction base="xs:integer">
> +                       <xs:minInclusive value="-1" />
> +                       <xs:maxInclusive value="2147483648000" />
> +               </xs:restriction>
> +       </xs:simpleType>
> +
>         <!-- Maps to the char name[LTTNG_SYMBOL_NAME_LEN] -->
>         <xs:simpleType name="name_type">
>                 <xs:restriction base="xs:string">
> @@ -363,6 +376,7 @@ THE SOFTWARE.
>                         <xs:element name="discarded_events" type="tns:uint64_type" default="0" minOccurs="0" />
>                         <xs:element name="lost_packets" type="tns:uint64_type" default="0" minOccurs="0" />
>                         <xs:element name="monitor_timer_interval" type="tns:uint64_type" default="0" minOccurs="0" />
> +                       <xs:element name="blocking_timeout" type="tns:blocking_timeout_type" default="0" minOccurs="0" />
>                 </xs:all>
>         </xs:complexType>
>
> diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c
> index 197add2..9c1597b 100644
> --- a/src/common/mi-lttng.c
> +++ b/src/common/mi-lttng.c
> @@ -863,6 +863,7 @@ int mi_lttng_channel_attr(struct mi_writer *writer,
>         struct lttng_channel *chan = caa_container_of(attr,
>                         struct lttng_channel, attr);
>         uint64_t discarded_events, lost_packets, monitor_timer_interval;
> +       int64_t blocking_timeout;
>
>         assert(attr);
>
> @@ -882,6 +883,12 @@ int mi_lttng_channel_attr(struct mi_writer *writer,
>                 goto end;
>         }
>
> +       ret = lttng_channel_get_blocking_timeout(chan,
> +                       &blocking_timeout);
> +       if (ret) {
> +               goto end;
> +       }
> +
>         /* Opening Attributes */
>         ret = mi_lttng_writer_open_element(writer, config_element_attributes);
>         if (ret) {
> @@ -936,6 +943,14 @@ int mi_lttng_channel_attr(struct mi_writer *writer,
>                 goto end;
>         }
>
> +       /* Retry timeout in usec */

The unit conversion is confusing in this patch.

The user-provided (CLI) argument is in usec and is then converted to
msec by the client, before being used as msec with liblttng-ctl
functions. Then, it is retrieved and output as-is (in msec) here and
in the human-readable listing.

I'll move the unit conversion to a single place (before we hand-off
the delay to lttng-ust) since the current convention is to store and
expose all timers in usec.

I'll also open an issue to add this property as part of the
"save/load" functionality before the realease.

Jérémie

> +       ret = mi_lttng_writer_write_element_signed_int(writer,
> +               config_element_blocking_timeout,
> +               blocking_timeout);
> +       if (ret) {
> +               goto end;
> +       }
> +
>         /* Event output */
>         ret = mi_lttng_writer_write_element_string(writer,
>                 config_element_output_type,
> diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h
> index f6179f3..cd5ee06 100644
> --- a/src/common/sessiond-comm/sessiond-comm.h
> +++ b/src/common/sessiond-comm/sessiond-comm.h
> @@ -482,6 +482,7 @@ struct lttcomm_consumer_msg {
>                          * because the application can be in the tracing for instance.
>                          */
>                         uint32_t ust_app_uid;
> +                       int64_t blocking_timeout;
>                         char root_shm_path[PATH_MAX];
>                         char shm_path[PATH_MAX];
>                 } LTTNG_PACKED ask_channel;
> diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c
> index 147fe8a..99803a6 100644
> --- a/src/common/ust-consumer/ust-consumer.c
> +++ b/src/common/ust-consumer/ust-consumer.c
> @@ -1456,6 +1456,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
>                 attr.read_timer_interval = msg.u.ask_channel.read_timer_interval;
>                 attr.chan_id = msg.u.ask_channel.chan_id;
>                 memcpy(attr.uuid, msg.u.ask_channel.uuid, sizeof(attr.uuid));
> +               attr.blocking_timeout= msg.u.ask_channel.blocking_timeout;
>
>                 /* Match channel buffer type to the UST abi. */
>                 switch (msg.u.ask_channel.output) {
> diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c
> index 6bd3f80..736114a 100644
> --- a/src/lib/lttng-ctl/lttng-ctl.c
> +++ b/src/lib/lttng-ctl/lttng-ctl.c
> @@ -2073,6 +2073,8 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain,
>                 if (extended) {
>                         extended->monitor_timer_interval =
>                                         DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
> +                       extended->blocking_timeout =
> +                                       DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
>                 }
>                 break;
>         case LTTNG_DOMAIN_UST:
> @@ -2088,6 +2090,8 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain,
>                         if (extended) {
>                                 extended->monitor_timer_interval =
>                                                 DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
> +                               extended->blocking_timeout =
> +                                               DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
>                         }
>                         break;
>                 case LTTNG_BUFFER_PER_PID:
> @@ -2102,6 +2106,8 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain,
>                         if (extended) {
>                                 extended->monitor_timer_interval =
>                                                 DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
> +                               extended->blocking_timeout =
> +                                               DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
>                         }
>                         break;
>                 }
> @@ -2203,6 +2209,44 @@ end:
>         return ret;
>  }
>
> +int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
> +               int64_t *blocking_timeout)
> +{
> +       int ret = 0;
> +
> +       if (!chan || !blocking_timeout) {
> +               ret = -LTTNG_ERR_INVALID;
> +               goto end;
> +       }
> +
> +       if (!chan->attr.extended.ptr) {
> +               ret = -LTTNG_ERR_INVALID;
> +               goto end;
> +       }
> +
> +       *blocking_timeout = ((struct lttng_channel_extended *)
> +                       chan->attr.extended.ptr)->blocking_timeout;
> +end:
> +       return ret;
> +}
> +
> +int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
> +               int64_t blocking_timeout)
> +{
> +       int ret = 0;
> +
> +       if (!chan || !chan->attr.extended.ptr) {
> +               ret = -LTTNG_ERR_INVALID;
> +               goto end;
> +       }
> +
> +       ((struct lttng_channel_extended *)
> +                       chan->attr.extended.ptr)->blocking_timeout =
> +                       blocking_timeout;
> +end:
> +       return ret;
> +}
> +
>  /*
>   * Check if session daemon is alive.
>   *
> diff --git a/tests/regression/ust/blocking/test_blocking b/tests/regression/ust/blocking/test_blocking
> index 261e0b8..c5c9590 100755
> --- a/tests/regression/ust/blocking/test_blocking
> +++ b/tests/regression/ust/blocking/test_blocking
> @@ -20,13 +20,14 @@ TEST_DESC="UST - Blocking mode"
>  CURDIR=$(dirname $0)/
>  TESTDIR=$CURDIR/../../..
>  SESSION_NAME="blocking"
> +CHANNEL_NAME="testchan"
>
>  TESTAPP_PATH="$TESTDIR/utils/testapp"
>  TESTAPP_NAME="gen-ust-events"
>  TESTAPP_BIN="$TESTAPP_PATH/$TESTAPP_NAME/$TESTAPP_NAME"
>  EVENT_NAME="tp:tptest"
>
> -NUM_TESTS=45
> +NUM_TESTS=49
>
>  source $TESTDIR/utils/utils.sh
>
> @@ -40,11 +41,11 @@ function run_app()
>
>  function test_ust_implicit_no_blocking()
>  {
> -       NUM_EVENT=500000
> +       NUM_EVENT=5000000
>         diag "UST implicit non-blocking mode (default): will hang if fails"
>
> -       # Test without the plugin
>         start_lttng_sessiond
> +       # session in no-output mode
>         create_lttng_session_no_output $SESSION_NAME
>         enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
>         start_lttng_tracing_ok $SESSION_NAME
> @@ -56,17 +57,18 @@ function test_ust_implicit_no_blocking()
>         ok 0 "Does not hang"
>  }
>
> -function test_ust_explicit_no_blocking()
> +function test_ust_implicit_no_blocking_with_channel_blocking()
>  {
> -       NUM_EVENT=500000
> -       diag "UST explicit non-blocking mode: will hang if fails"
> +       NUM_EVENT=5000000
> +       diag "UST implicit non-blocking mode (default) with blocking-timeout=-1 channel: will hang if fails"
>
> -       # Test without the plugin
>         start_lttng_sessiond
> +       # session in no-output mode
>         create_lttng_session_no_output $SESSION_NAME
> -       enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
> +       enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=-1"
> +       enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
>         start_lttng_tracing_ok $SESSION_NAME
> -       LTTNG_UST_BLOCKING_RETRY_TIMEOUT=0 run_app
> +       run_app
>         stop_lttng_tracing_ok $SESSION_NAME
>         destroy_lttng_session_ok $SESSION_NAME
>         stop_lttng_sessiond
> @@ -77,14 +79,16 @@ function test_ust_explicit_no_blocking()
>  function test_ust_timeout_no_blocking()
>  {
>         NUM_EVENT=12500
> -       diag "UST 1ms timeout retry mode: will hang if fails"
> +       diag "UST 1ms timeout blocking mode: will hang if fails"
>
>         start_lttng_sessiond
> +       # session in no-output mode
>         create_lttng_session_no_output $SESSION_NAME
> -       enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
> +       # blocking timeout 1ms
> +       enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=1000"
> +       enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
>         start_lttng_tracing_ok $SESSION_NAME
> -       # retry timeout 1ms
> -       LTTNG_UST_BLOCKING_RETRY_TIMEOUT=1 run_app
> +       LTTNG_UST_ALLOW_BLOCKING=1 run_app
>         stop_lttng_tracing_ok $SESSION_NAME
>         destroy_lttng_session_ok $SESSION_NAME
>         stop_lttng_sessiond
> @@ -94,15 +98,17 @@ function test_ust_timeout_no_blocking()
>
>  function test_ust_snapshot_no_blocking()
>  {
> -       NUM_EVENT=500000
> +       NUM_EVENT=5000000
>         diag "UST blocking mode: don't block in snapshot mode"
>
>         # Test without the plugin
>         start_lttng_sessiond
>         create_lttng_session_ok $SESSION_NAME $TRACE_PATH --snapshot
> -       enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
> +       # blocking timeout 1ms
> +       enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=1000"
> +       enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
>         start_lttng_tracing_ok $SESSION_NAME
> -       LTTNG_UST_BLOCKING_RETRY_TIMEOUT=-1 run_app
> +       LTTNG_UST_ALLOW_BLOCKING=1 run_app
>         stop_lttng_tracing_ok $SESSION_NAME
>         destroy_lttng_session_ok $SESSION_NAME
>         stop_lttng_sessiond
> @@ -112,16 +118,17 @@ function test_ust_snapshot_no_blocking()
>
>  function test_ust_blocking_no_discard()
>  {
> -       NUM_EVENT=500000
> +       NUM_EVENT=5000000
>         diag "UST blocking mode: no event discarded"
>
>         # Test without the plugin
>         start_lttng_sessiond
>         create_lttng_session_ok $SESSION_NAME $TRACE_PATH
> -       enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
> +       # infinite blocking timeout
> +       enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=-1"
> +       enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
>         start_lttng_tracing_ok $SESSION_NAME
> -       # infinite retry timeout
> -       LTTNG_UST_BLOCKING_RETRY_TIMEOUT=-1 run_app
> +       LTTNG_UST_ALLOW_BLOCKING=1 run_app
>         stop_lttng_tracing_ok $SESSION_NAME
>         destroy_lttng_session_ok $SESSION_NAME
>         stop_lttng_sessiond
> @@ -138,7 +145,7 @@ print_test_banner "$TEST_DESC"
>
>  TESTS=(
>         "test_ust_implicit_no_blocking"
> -       "test_ust_explicit_no_blocking"
> +       "test_ust_implicit_no_blocking_with_channel_blocking"
>         "test_ust_timeout_no_blocking"
>         "test_ust_snapshot_no_blocking"
>         "test_ust_blocking_no_discard"
> --
> 2.1.4
>
Mathieu Desnoyers June 12, 2017, 9:57 p.m. UTC | #2
----- On Jun 12, 2017, at 5:28 PM, Jeremie Galarneau jeremie.galarneau at efficios.com wrote:


>>
>> +       /* Retry timeout in usec */
> 
> The unit conversion is confusing in this patch.
> 
> The user-provided (CLI) argument is in usec and is then converted to
> msec by the client, before being used as msec with liblttng-ctl
> functions. Then, it is retrieved and output as-is (in msec) here and
> in the human-readable listing.
> 
> I'll move the unit conversion to a single place (before we hand-off
> the delay to lttng-ust) since the current convention is to store and
> expose all timers in usec.
> 

As discussed, the CLI only does an overflow check, not a conversion.
Let's simply add this overflow check in the lib too, so we can
return "invalid parameter" to the caller.

> I'll also open an issue to add this property as part of the
> "save/load" functionality before the realease.

OK,

Thanks!

Mathieu
Jérémie Galarneau June 12, 2017, 10:14 p.m. UTC | #3
Merged in master and stable-2.10 with the supplementary checks.

Thanks!
Jérémie

On 12 June 2017 at 17:57, Mathieu Desnoyers
<mathieu.desnoyers at efficios.com> wrote:
>
>
> ----- On Jun 12, 2017, at 5:28 PM, Jeremie Galarneau jeremie.galarneau at efficios.com wrote:
>
>
>>>
>>> +       /* Retry timeout in usec */
>>
>> The unit conversion is confusing in this patch.
>>
>> The user-provided (CLI) argument is in usec and is then converted to
>> msec by the client, before being used as msec with liblttng-ctl
>> functions. Then, it is retrieved and output as-is (in msec) here and
>> in the human-readable listing.
>>
>> I'll move the unit conversion to a single place (before we hand-off
>> the delay to lttng-ust) since the current convention is to store and
>> expose all timers in usec.
>>
>
> As discussed, the CLI only does an overflow check, not a conversion.
> Let's simply add this overflow check in the lib too, so we can
> return "invalid parameter" to the caller.
>
>> I'll also open an issue to add this property as part of the
>> "save/load" functionality before the realease.
>
> OK,
>
> Thanks!
>
> Mathieu
>
> --
> Mathieu Desnoyers
> EfficiOS Inc.
> http://www.efficios.com
diff mbox

Patch

diff --git a/configure.ac b/configure.ac
index 9239e3b..19f2d67 100644
--- a/configure.ac
+++ b/configure.ac
@@ -246,6 +246,7 @@  m4_define([_DEFAULT_CHANNEL_SWITCH_TIMER], [0])
 m4_define([_DEFAULT_CHANNEL_LIVE_TIMER], [0])
 m4_define([_DEFAULT_CHANNEL_READ_TIMER], [200000])
 m4_define([_DEFAULT_CHANNEL_MONITOR_TIMER], [1000000])
+m4_define([_DEFAULT_CHANNEL_BLOCKING_TIMEOUT], [0])
 _AC_DEFINE_AND_SUBST([DEFAULT_AGENT_TCP_PORT], [5345])
 _AC_DEFINE_AND_SUBST([DEFAULT_APP_SOCKET_RW_TIMEOUT], [5])
 _AC_DEFINE_AND_SUBST([DEFAULT_CHANNEL_SUBBUF_SIZE], [_DEFAULT_CHANNEL_SUBBUF_SIZE])
@@ -257,6 +258,7 @@  _AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM], [_DEFAULT_CHANNEL_SUBB
 _AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE], [1048576])
 _AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER], [_DEFAULT_CHANNEL_SWITCH_TIMER])
 _AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER], [_DEFAULT_CHANNEL_MONITOR_TIMER])
+_AC_DEFINE_AND_SUBST([DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT], [_DEFAULT_CHANNEL_BLOCKING_TIMEOUT])
 _AC_DEFINE_AND_SUBST([DEFAULT_LTTNG_LIVE_TIMER], [1000000])
 _AC_DEFINE_AND_SUBST([DEFAULT_METADATA_CACHE_SIZE], [4096])
 _AC_DEFINE_AND_SUBST([DEFAULT_METADATA_READ_TIMER], [0])
@@ -268,12 +270,14 @@  _AC_DEFINE_AND_SUBST([DEFAULT_NETWORK_DATA_PORT], [5343])
 _AC_DEFINE_AND_SUBST([DEFAULT_NETWORK_VIEWER_PORT], [5344])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_LIVE_TIMER], [_DEFAULT_CHANNEL_LIVE_TIMER])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_READ_TIMER], [0])
+_AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT], [0])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM], [_DEFAULT_CHANNEL_SUBBUF_NUM])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_SUBBUF_SIZE], [_DEFAULT_CHANNEL_SUBBUF_SIZE])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER], [_DEFAULT_CHANNEL_SWITCH_TIMER])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER], [_DEFAULT_CHANNEL_MONITOR_TIMER])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_LIVE_TIMER], [_DEFAULT_CHANNEL_LIVE_TIMER])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_READ_TIMER], [0])
+_AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT], [0])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM], [_DEFAULT_CHANNEL_SUBBUF_NUM])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_SUBBUF_SIZE], [524288])
 _AC_DEFINE_AND_SUBST([DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER], [_DEFAULT_CHANNEL_SWITCH_TIMER])
diff --git a/doc/man/lttng-enable-channel.1.txt b/doc/man/lttng-enable-channel.1.txt
index f9b0b1f..d66d2fb 100644
--- a/doc/man/lttng-enable-channel.1.txt
+++ b/doc/man/lttng-enable-channel.1.txt
@@ -26,6 +26,7 @@  Create a user space channel:
       [option:--overwrite] [option:--buffers-pid]
       [option:--subbuf-size='SIZE'] [option:--num-subbuf='COUNT']
       [option:--switch-timer='PERIODUS'] [option:--read-timer='PERIODUS']
+      [option:--blocking-timeout='TIMEOUTUS']
       [option:--tracefile-size='SIZE'] [option:--tracefile-count='COUNT']
       [option:--session='SESSION'] 'CHANNEL'
 
@@ -358,6 +359,16 @@  Default values:
 * option:--kernel option: {default_kernel_channel_switch_timer}
 * `metadata` channel: {default_metadata_switch_timer}
 
+Timeouts
+~~~~~~~~
+option:--blocking-timeout:
+    Set the channel's blocking timeout value to 'TIMEOUTUS' µs. 0
+    (default) does not block. -1 blocks forever until room is
+    available in the buffer to write the event. Positive
+    values are a timeout bounding the maximum blocking time
+    when trying to write into the buffer. Note that this option
+    only affects applications launched with the
+    LTTNG_UST_ALLOW_BLOCKING environment variable set.
 
 include::common-cmd-help-options.txt[]
 
@@ -385,4 +396,5 @@  include::common-cmd-footer.txt[]
 SEE ALSO
 --------
 man:lttng-disable-channel(1),
-man:lttng(1)
+man:lttng(1),
+man:lttng-ust(3)
diff --git a/include/lttng/channel-internal.h b/include/lttng/channel-internal.h
index d78a720..53171f4 100644
--- a/include/lttng/channel-internal.h
+++ b/include/lttng/channel-internal.h
@@ -22,6 +22,7 @@  struct lttng_channel_extended {
 	uint64_t discarded_events;
 	uint64_t lost_packets;
 	uint64_t monitor_timer_interval;
+	int64_t blocking_timeout;
 } LTTNG_PACKED;
 
 #endif /* LTTNG_CHANNEL_INTERNAL_H */
diff --git a/include/lttng/channel.h b/include/lttng/channel.h
index e20ed4f..4e61a61 100644
--- a/include/lttng/channel.h
+++ b/include/lttng/channel.h
@@ -138,6 +138,12 @@  extern int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan,
 extern int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan,
 		uint64_t monitor_timer_interval);
 
+extern int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
+		int64_t *blocking_timeout);
+
+extern int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
+		int64_t blocking_timeout);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/bin/lttng-sessiond/channel.c b/src/bin/lttng-sessiond/channel.c
index 8a88ecc..5aa0cd8 100644
--- a/src/bin/lttng-sessiond/channel.c
+++ b/src/bin/lttng-sessiond/channel.c
@@ -72,6 +72,7 @@  struct lttng_channel *channel_new_default_attr(int dom,
 		chan->attr.switch_timer_interval = DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER;
 		chan->attr.read_timer_interval = DEFAULT_KERNEL_CHANNEL_READ_TIMER;
 		chan->attr.live_timer_interval = DEFAULT_KERNEL_CHANNEL_LIVE_TIMER;
+		extended_attr->blocking_timeout = DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
 		extended_attr->monitor_timer_interval =
 			DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
 		break;
@@ -97,6 +98,7 @@  common_ust:
 				DEFAULT_UST_UID_CHANNEL_READ_TIMER;
 			chan->attr.live_timer_interval =
 				DEFAULT_UST_UID_CHANNEL_LIVE_TIMER;
+			extended_attr->blocking_timeout = DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
 			extended_attr->monitor_timer_interval =
 				DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
 			break;
@@ -111,6 +113,7 @@  common_ust:
 				DEFAULT_UST_PID_CHANNEL_READ_TIMER;
 			chan->attr.live_timer_interval =
 				DEFAULT_UST_PID_CHANNEL_LIVE_TIMER;
+			extended_attr->blocking_timeout = DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
 			extended_attr->monitor_timer_interval =
 				DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
 			break;
@@ -217,6 +220,15 @@  static int channel_validate(struct lttng_channel *attr)
 	return 0;
 }
 
+static int channel_validate_kernel(struct lttng_channel *attr)
+{
+	/* Kernel channels do not support blocking timeout. */
+	if (((struct lttng_channel_extended *)attr->attr.extended.ptr)->blocking_timeout) {
+		return -1;
+	}
+	return 0;
+}
+
 /*
  * Create kernel channel of the kernel session and notify kernel thread.
  */
@@ -258,6 +270,11 @@  int channel_kernel_create(struct ltt_kernel_session *ksession,
 		goto error;
 	}
 
+	if (channel_validate_kernel(attr) < 0) {
+		ret = LTTNG_ERR_INVALID;
+		goto error;
+	}
+
 	/* Channel not found, creating it */
 	ret = kernel_create_channel(ksession, attr);
 	if (ret < 0) {
diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c
index dea5ab2..73a309d 100644
--- a/src/bin/lttng-sessiond/cmd.c
+++ b/src/bin/lttng-sessiond/cmd.c
@@ -277,6 +277,7 @@  static ssize_t list_lttng_channels(enum lttng_domain_type domain,
 				chan_exts[i].lost_packets = lost_packets;
 				chan_exts[i].monitor_timer_interval =
 						extended->monitor_timer_interval;
+				chan_exts[i].blocking_timeout = 0;
 				i++;
 			}
 		}
@@ -324,6 +325,8 @@  static ssize_t list_lttng_channels(enum lttng_domain_type domain,
 
 			chan_exts[i].monitor_timer_interval =
 					uchan->monitor_timer_interval;
+			chan_exts[i].blocking_timeout =
+				uchan->attr.u.s.blocking_timeout;
 
 			ret = get_ust_runtime_stats(session, uchan,
 					&discarded_events, &lost_packets);
diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c
index 4a7287b..33ccfe2 100644
--- a/src/bin/lttng-sessiond/consumer.c
+++ b/src/bin/lttng-sessiond/consumer.c
@@ -822,6 +822,7 @@  void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg,
 		uint64_t session_id_per_pid,
 		unsigned int monitor,
 		uint32_t ust_app_uid,
+		int64_t blocking_timeout,
 		const char *root_shm_path,
 		const char *shm_path)
 {
@@ -851,6 +852,7 @@  void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg,
 	msg->u.ask_channel.tracefile_count = tracefile_count;
 	msg->u.ask_channel.monitor = monitor;
 	msg->u.ask_channel.ust_app_uid = ust_app_uid;
+	msg->u.ask_channel.blocking_timeout = blocking_timeout;
 
 	memcpy(msg->u.ask_channel.uuid, uuid, sizeof(msg->u.ask_channel.uuid));
 
diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h
index 77bc2b1..b8d5630 100644
--- a/src/bin/lttng-sessiond/consumer.h
+++ b/src/bin/lttng-sessiond/consumer.h
@@ -256,6 +256,7 @@  void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg,
 		uint64_t session_id_per_pid,
 		unsigned int monitor,
 		uint32_t ust_app_uid,
+		int64_t blocking_timeout,
 		const char *root_shm_path,
 		const char *shm_path);
 void consumer_init_stream_comm_msg(struct lttcomm_consumer_msg *msg,
diff --git a/src/bin/lttng-sessiond/lttng-ust-abi.h b/src/bin/lttng-sessiond/lttng-ust-abi.h
index 972de0c..687eb0b 100644
--- a/src/bin/lttng-sessiond/lttng-ust-abi.h
+++ b/src/bin/lttng-sessiond/lttng-ust-abi.h
@@ -181,7 +181,12 @@  struct lttng_ust_channel_attr {
 	unsigned int switch_timer_interval;	/* usec */
 	unsigned int read_timer_interval;	/* usec */
 	enum lttng_ust_output output;		/* splice, mmap */
-	char padding[LTTNG_UST_CHANNEL_ATTR_PADDING];
+	union {
+		struct {
+			int64_t blocking_timeout;	/* Retry timeout (usec) */
+		} s;
+		char padding[LTTNG_UST_CHANNEL_ATTR_PADDING];
+	} u;
 } LTTNG_PACKED;
 
 #define LTTNG_UST_TRACEPOINT_ITER_PADDING	16
diff --git a/src/bin/lttng-sessiond/lttng-ust-ctl.h b/src/bin/lttng-sessiond/lttng-ust-ctl.h
index cba0e27..1d67e85 100644
--- a/src/bin/lttng-sessiond/lttng-ust-ctl.h
+++ b/src/bin/lttng-sessiond/lttng-ust-ctl.h
@@ -53,6 +53,7 @@  struct ustctl_consumer_channel_attr {
 	enum lttng_ust_output output;		/* splice, mmap */
 	uint32_t chan_id;           /* channel ID */
 	unsigned char uuid[LTTNG_UST_UUID_LEN]; /* Trace session unique ID */
+	int64_t blocking_timeout;			/* Retry timeout (usec) */
 } LTTNG_PACKED;
 
 /*
diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c
index 314c21e..bcb04fe 100644
--- a/src/bin/lttng-sessiond/trace-ust.c
+++ b/src/bin/lttng-sessiond/trace-ust.c
@@ -358,6 +358,8 @@  struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan,
 	luc->attr.output = (enum lttng_ust_output) chan->attr.output;
 	luc->monitor_timer_interval = ((struct lttng_channel_extended *)
 			chan->attr.extended.ptr)->monitor_timer_interval;
+	luc->attr.u.s.blocking_timeout = ((struct lttng_channel_extended *)
+			chan->attr.extended.ptr)->blocking_timeout;
 
 	/* Translate to UST output enum */
 	switch (luc->attr.output) {
diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c
index 8176d4d..df46f42 100644
--- a/src/bin/lttng-sessiond/ust-app.c
+++ b/src/bin/lttng-sessiond/ust-app.c
@@ -92,6 +92,7 @@  static void copy_channel_attr_to_ustctl(
 	attr->switch_timer_interval = uattr->switch_timer_interval;
 	attr->read_timer_interval = uattr->read_timer_interval;
 	attr->output = uattr->output;
+	attr->blocking_timeout = uattr->u.s.blocking_timeout;
 }
 
 /*
@@ -1035,6 +1036,7 @@  struct ust_app_channel *alloc_ust_app_channel(char *name,
 		ua_chan->attr.switch_timer_interval = attr->switch_timer_interval;
 		ua_chan->attr.read_timer_interval = attr->read_timer_interval;
 		ua_chan->attr.output = attr->output;
+		ua_chan->attr.blocking_timeout = attr->u.s.blocking_timeout;
 	}
 	/* By default, the channel is a per cpu channel. */
 	ua_chan->attr.type = LTTNG_UST_CHAN_PER_CPU;
@@ -1798,6 +1800,8 @@  static void shadow_copy_channel(struct ust_app_channel *ua_chan,
 	ua_chan->attr.read_timer_interval = uchan->attr.read_timer_interval;
 	ua_chan->monitor_timer_interval = uchan->monitor_timer_interval;
 	ua_chan->attr.output = uchan->attr.output;
+	ua_chan->attr.blocking_timeout = uchan->attr.u.s.blocking_timeout;
+
 	/*
 	 * Note that the attribute channel type is not set since the channel on the
 	 * tracing registry side does not have this information.
diff --git a/src/bin/lttng-sessiond/ust-consumer.c b/src/bin/lttng-sessiond/ust-consumer.c
index fe2c8f4..43bf261 100644
--- a/src/bin/lttng-sessiond/ust-consumer.c
+++ b/src/bin/lttng-sessiond/ust-consumer.c
@@ -192,6 +192,7 @@  static int ask_channel_creation(struct ust_app_session *ua_sess,
 			ua_sess->id,
 			ua_sess->output_traces,
 			ua_sess->uid,
+			ua_chan->attr.blocking_timeout,
 			root_shm_path, shm_path);
 
 	health_code_update();
diff --git a/src/bin/lttng/commands/enable_channels.c b/src/bin/lttng/commands/enable_channels.c
index 22331ce..9d71720 100644
--- a/src/bin/lttng/commands/enable_channels.c
+++ b/src/bin/lttng/commands/enable_channels.c
@@ -48,6 +48,10 @@  static struct {
 	bool set;
 	uint32_t interval;
 } opt_monitor_timer;
+static struct {
+	bool set;
+	int64_t value;
+} opt_blocking_timeout;
 
 static struct mi_writer *writer;
 
@@ -70,6 +74,7 @@  enum {
 	OPT_LIST_OPTIONS,
 	OPT_TRACEFILE_SIZE,
 	OPT_TRACEFILE_COUNT,
+	OPT_BLOCKING_TIMEOUT,
 };
 
 static struct lttng_handle *handle;
@@ -97,6 +102,7 @@  static struct poptOption long_options[] = {
 	{"buffers-global", 0,	POPT_ARG_VAL, &opt_buffer_global, 1, 0, 0},
 	{"tracefile-size", 'C',   POPT_ARG_INT, 0, OPT_TRACEFILE_SIZE, 0, 0},
 	{"tracefile-count", 'W',   POPT_ARG_INT, 0, OPT_TRACEFILE_COUNT, 0, 0},
+	{"blocking-timeout",     0,   POPT_ARG_INT, 0, OPT_BLOCKING_TIMEOUT, 0, 0},
 	{0, 0, 0, 0, 0, 0, 0}
 };
 
@@ -151,6 +157,15 @@  static int enable_channel(char *session_name)
 
 	memset(&dom, 0, sizeof(dom));
 
+	/* Validate options. */
+	if (opt_kernel) {
+		if (opt_blocking_timeout.set) {
+			ERR("Retry timeout option not supported for kernel domain (-k)");
+			ret = CMD_ERROR;
+			goto error;
+		}
+	}
+
 	/* Create lttng domain */
 	if (opt_kernel) {
 		dom.type = LTTNG_DOMAIN_KERNEL;
@@ -262,6 +277,15 @@  static int enable_channel(char *session_name)
 				goto error;
 			}
 		}
+		if (opt_blocking_timeout.set) {
+			ret = lttng_channel_set_blocking_timeout(channel,
+					opt_blocking_timeout.value);
+			if (ret) {
+				ERR("Failed to set the channel's blocking timeout");
+				error = 1;
+				goto error;
+			}
+		}
 
 		DBG("Enabling channel %s", channel_name);
 
@@ -530,6 +554,34 @@  int cmd_enable_channels(int argc, const char **argv)
 			DBG("Channel monitor timer interval set to %d", opt_monitor_timer.interval);
 			break;
 		}
+		case OPT_BLOCKING_TIMEOUT:
+		{
+			long long v;	/* in usec */
+			long long v_msec;
+
+			errno = 0;
+			opt_arg = poptGetOptArg(pc);
+			v = strtoll(opt_arg, NULL, 0);
+			if (errno != 0 || (!isdigit(opt_arg[0]) && opt_arg[0] != '-')
+					|| v < -1) {
+				ERR("Wrong value in --blocking_timeout parameter: %s", opt_arg);
+				ret = CMD_ERROR;
+				goto end;
+			}
+			if (v >= 0) {
+				v_msec = v / 1000;
+				if (v_msec != (int32_t) v_msec) {
+					ERR("32-bit milliseconds overflow in --blocking_timeout parameter: %s", opt_arg);
+					ret = CMD_ERROR;
+					goto end;
+				}
+			}
+			opt_blocking_timeout.value = (int64_t) v;
+			opt_blocking_timeout.set = true;
+			DBG("Channel blocking timeout set to %" PRId64 " (µs)",
+				opt_blocking_timeout.value);
+			break;
+		}
 		case OPT_USERSPACE:
 			opt_userspace = 1;
 			break;
diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c
index 1315783..942e4a4 100644
--- a/src/bin/lttng/commands/list.c
+++ b/src/bin/lttng/commands/list.c
@@ -1173,6 +1173,7 @@  static void print_channel(struct lttng_channel *channel)
 {
 	int ret;
 	uint64_t discarded_events, lost_packets, monitor_timer_interval;
+	int64_t blocking_timeout;
 
 	ret = lttng_channel_get_discarded_event_count(channel,
 			&discarded_events);
@@ -1195,6 +1196,13 @@  static void print_channel(struct lttng_channel *channel)
 		return;
 	}
 
+	ret = lttng_channel_get_blocking_timeout(channel,
+			&blocking_timeout);
+	if (ret) {
+		ERR("Failed to retrieve blocking timeout of channel");
+		return;
+	}
+
 	MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
 
 	MSG("%sAttributes:", indent4);
@@ -1204,6 +1212,7 @@  static void print_channel(struct lttng_channel *channel)
 	MSG("%sswitch timer interval: %u", indent6, channel->attr.switch_timer_interval);
 	MSG("%sread timer interval: %u", indent6, channel->attr.read_timer_interval);
 	MSG("%smonitor timer interval: %" PRIu64, indent6, monitor_timer_interval);
+	MSG("%sblocking timeout (µs): %" PRId64, indent6, blocking_timeout);
 	MSG("%strace file count: %" PRIu64, indent6, channel->attr.tracefile_count);
 	MSG("%strace file size (bytes): %" PRIu64, indent6, channel->attr.tracefile_size);
 	MSG("%sdiscarded events: %" PRIu64, indent6, discarded_events);
diff --git a/src/common/config/config-session-abi.h b/src/common/config/config-session-abi.h
index 2faa354..5f91109 100644
--- a/src/common/config/config-session-abi.h
+++ b/src/common/config/config-session-abi.h
@@ -42,6 +42,7 @@  extern const char * const config_element_num_subbuf;
 extern const char * const config_element_switch_timer_interval;
 extern const char * const config_element_read_timer_interval;
 extern const char * const config_element_monitor_timer_interval;
+extern const char * const config_element_blocking_timeout;
 extern const char * const config_element_output;
 extern const char * const config_element_output_type;
 extern const char * const config_element_tracefile_size;
diff --git a/src/common/config/session-config.c b/src/common/config/session-config.c
index 69b62d7..a629312 100644
--- a/src/common/config/session-config.c
+++ b/src/common/config/session-config.c
@@ -92,6 +92,7 @@  const char * const config_element_num_subbuf = "subbuffer_count";
 const char * const config_element_switch_timer_interval = "switch_timer_interval";
 const char * const config_element_read_timer_interval = "read_timer_interval";
 const char * const config_element_monitor_timer_interval = "monitor_timer_interval";
+const char * const config_element_blocking_timeout = "blocking_timeout";
 const char * const config_element_output = "output";
 const char * const config_element_output_type = "output_type";
 const char * const config_element_tracefile_size = "tracefile_size";
diff --git a/src/common/config/session.xsd b/src/common/config/session.xsd
index 550fea0..6efdc43 100644
--- a/src/common/config/session.xsd
+++ b/src/common/config/session.xsd
@@ -43,6 +43,18 @@  elementFormDefault="qualified" version="2.8">
 	</xs:restriction>
 </xs:simpleType>
 
+<!--
+Maps to the range allowed for blocking timeout: -1 (block forever),
+0 (do not block), positive integer value (blocking time in usec) limited
+by its signed 32-bit representation when converted to msec.
+-->
+<xs:simpleType name="blocking_timeout_type">
+	<xs:restriction base="xs:integer">
+		<xs:minInclusive value="-1" />
+		<xs:maxInclusive value="2147483648000" />
+	</xs:restriction>
+</xs:simpleType>
+
 <xs:simpleType name="channel_overwrite_mode_type">
 	<xs:restriction base="xs:string">
 		<xs:enumeration value="DISCARD"/>
@@ -186,6 +198,7 @@  elementFormDefault="qualified" version="2.8">
 		<xs:element name="subbuffer_count" type="uint64_type" default="4" minOccurs="0"/>
 		<xs:element name="switch_timer_interval" type="uint32_type" default="0" minOccurs="0"/>  <!-- usec -->
 		<xs:element name="read_timer_interval" type="uint32_type"/>  <!-- usec -->
+		<xs:element name="blocking_timeout" type="blocking_timeout_type" default="0" minOccurs="0" /> <!-- usec -->
 		<xs:element name="output_type" type="event_output_type"/>
 		<xs:element name="tracefile_size" type="uint64_type" default="0" minOccurs="0"/> <!-- bytes -->
 		<xs:element name="tracefile_count" type="uint64_type" default="0" minOccurs="0"/>
diff --git a/src/common/defaults.h b/src/common/defaults.h
index e0d0d86..b810302 100644
--- a/src/common/defaults.h
+++ b/src/common/defaults.h
@@ -221,6 +221,7 @@ 
 #define DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER	CONFIG_DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER
 #define DEFAULT_KERNEL_CHANNEL_READ_TIMER	CONFIG_DEFAULT_KERNEL_CHANNEL_READ_TIMER
 #define DEFAULT_KERNEL_CHANNEL_LIVE_TIMER	CONFIG_DEFAULT_KERNEL_CHANNEL_LIVE_TIMER
+#define DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT	CONFIG_DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT
 
 /* User space defaults */
 
@@ -244,6 +245,9 @@ 
 #define DEFAULT_UST_PID_CHANNEL_READ_TIMER      CONFIG_DEFAULT_UST_PID_CHANNEL_READ_TIMER
 #define DEFAULT_UST_UID_CHANNEL_READ_TIMER      CONFIG_DEFAULT_UST_UID_CHANNEL_READ_TIMER
 
+#define DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT	CONFIG_DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT
+#define DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT	CONFIG_DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT
+
 /*
  * Default timeout value for the sem_timedwait() call. Blocking forever is not
  * wanted so a timeout is used to control the data flow and not freeze the
diff --git a/src/common/mi-lttng-3.0.xsd b/src/common/mi-lttng-3.0.xsd
index 56b65a3..8b2e453 100644
--- a/src/common/mi-lttng-3.0.xsd
+++ b/src/common/mi-lttng-3.0.xsd
@@ -43,6 +43,19 @@  THE SOFTWARE.
 		</xs:restriction>
 	</xs:simpleType>
 
+	<!--
+	Maps to the range allowed for blocking timeout: -1 (block
+	forever), 0 (do not block), positive integer value (blocking
+	time in usec) limited by its signed 32-bit representation when
+	converted to msec.
+	-->
+	<xs:simpleType name="blocking_timeout_type">
+		<xs:restriction base="xs:integer">
+			<xs:minInclusive value="-1" />
+			<xs:maxInclusive value="2147483648000" />
+		</xs:restriction>
+	</xs:simpleType>
+
 	<!-- Maps to the char name[LTTNG_SYMBOL_NAME_LEN] -->
 	<xs:simpleType name="name_type">
 		<xs:restriction base="xs:string">
@@ -363,6 +376,7 @@  THE SOFTWARE.
 			<xs:element name="discarded_events" type="tns:uint64_type" default="0" minOccurs="0" />
 			<xs:element name="lost_packets" type="tns:uint64_type" default="0" minOccurs="0" />
 			<xs:element name="monitor_timer_interval" type="tns:uint64_type" default="0" minOccurs="0" />
+			<xs:element name="blocking_timeout" type="tns:blocking_timeout_type" default="0" minOccurs="0" />
 		</xs:all>
 	</xs:complexType>
 
diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c
index 197add2..9c1597b 100644
--- a/src/common/mi-lttng.c
+++ b/src/common/mi-lttng.c
@@ -863,6 +863,7 @@  int mi_lttng_channel_attr(struct mi_writer *writer,
 	struct lttng_channel *chan = caa_container_of(attr,
 			struct lttng_channel, attr);
 	uint64_t discarded_events, lost_packets, monitor_timer_interval;
+	int64_t blocking_timeout;
 
 	assert(attr);
 
@@ -882,6 +883,12 @@  int mi_lttng_channel_attr(struct mi_writer *writer,
 		goto end;
 	}
 
+	ret = lttng_channel_get_blocking_timeout(chan,
+			&blocking_timeout);
+	if (ret) {
+		goto end;
+	}
+
 	/* Opening Attributes */
 	ret = mi_lttng_writer_open_element(writer, config_element_attributes);
 	if (ret) {
@@ -936,6 +943,14 @@  int mi_lttng_channel_attr(struct mi_writer *writer,
 		goto end;
 	}
 
+	/* Retry timeout in usec */
+	ret = mi_lttng_writer_write_element_signed_int(writer,
+		config_element_blocking_timeout,
+		blocking_timeout);
+	if (ret) {
+		goto end;
+	}
+
 	/* Event output */
 	ret = mi_lttng_writer_write_element_string(writer,
 		config_element_output_type,
diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h
index f6179f3..cd5ee06 100644
--- a/src/common/sessiond-comm/sessiond-comm.h
+++ b/src/common/sessiond-comm/sessiond-comm.h
@@ -482,6 +482,7 @@  struct lttcomm_consumer_msg {
 			 * because the application can be in the tracing for instance.
 			 */
 			uint32_t ust_app_uid;
+			int64_t blocking_timeout;
 			char root_shm_path[PATH_MAX];
 			char shm_path[PATH_MAX];
 		} LTTNG_PACKED ask_channel;
diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c
index 147fe8a..99803a6 100644
--- a/src/common/ust-consumer/ust-consumer.c
+++ b/src/common/ust-consumer/ust-consumer.c
@@ -1456,6 +1456,7 @@  int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
 		attr.read_timer_interval = msg.u.ask_channel.read_timer_interval;
 		attr.chan_id = msg.u.ask_channel.chan_id;
 		memcpy(attr.uuid, msg.u.ask_channel.uuid, sizeof(attr.uuid));
+		attr.blocking_timeout= msg.u.ask_channel.blocking_timeout;
 
 		/* Match channel buffer type to the UST abi. */
 		switch (msg.u.ask_channel.output) {
diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c
index 6bd3f80..736114a 100644
--- a/src/lib/lttng-ctl/lttng-ctl.c
+++ b/src/lib/lttng-ctl/lttng-ctl.c
@@ -2073,6 +2073,8 @@  void lttng_channel_set_default_attr(struct lttng_domain *domain,
 		if (extended) {
 			extended->monitor_timer_interval =
 					DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
+			extended->blocking_timeout =
+					DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
 		}
 		break;
 	case LTTNG_DOMAIN_UST:
@@ -2088,6 +2090,8 @@  void lttng_channel_set_default_attr(struct lttng_domain *domain,
 			if (extended) {
 				extended->monitor_timer_interval =
 						DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
+				extended->blocking_timeout =
+						DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
 			}
 			break;
 		case LTTNG_BUFFER_PER_PID:
@@ -2102,6 +2106,8 @@  void lttng_channel_set_default_attr(struct lttng_domain *domain,
 			if (extended) {
 				extended->monitor_timer_interval =
 						DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
+				extended->blocking_timeout =
+						DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
 			}
 			break;
 		}
@@ -2203,6 +2209,44 @@  end:
 	return ret;
 }
 
+int lttng_channel_get_blocking_timeout(struct lttng_channel *chan,
+		int64_t *blocking_timeout)
+{
+	int ret = 0;
+
+	if (!chan || !blocking_timeout) {
+		ret = -LTTNG_ERR_INVALID;
+		goto end;
+	}
+
+	if (!chan->attr.extended.ptr) {
+		ret = -LTTNG_ERR_INVALID;
+		goto end;
+	}
+
+	*blocking_timeout = ((struct lttng_channel_extended *)
+			chan->attr.extended.ptr)->blocking_timeout;
+end:
+	return ret;
+}
+
+int lttng_channel_set_blocking_timeout(struct lttng_channel *chan,
+		int64_t blocking_timeout)
+{
+	int ret = 0;
+
+	if (!chan || !chan->attr.extended.ptr) {
+		ret = -LTTNG_ERR_INVALID;
+		goto end;
+	}
+
+	((struct lttng_channel_extended *)
+			chan->attr.extended.ptr)->blocking_timeout =
+			blocking_timeout;
+end:
+	return ret;
+}
+
 /*
  * Check if session daemon is alive.
  *
diff --git a/tests/regression/ust/blocking/test_blocking b/tests/regression/ust/blocking/test_blocking
index 261e0b8..c5c9590 100755
--- a/tests/regression/ust/blocking/test_blocking
+++ b/tests/regression/ust/blocking/test_blocking
@@ -20,13 +20,14 @@  TEST_DESC="UST - Blocking mode"
 CURDIR=$(dirname $0)/
 TESTDIR=$CURDIR/../../..
 SESSION_NAME="blocking"
+CHANNEL_NAME="testchan"
 
 TESTAPP_PATH="$TESTDIR/utils/testapp"
 TESTAPP_NAME="gen-ust-events"
 TESTAPP_BIN="$TESTAPP_PATH/$TESTAPP_NAME/$TESTAPP_NAME"
 EVENT_NAME="tp:tptest"
 
-NUM_TESTS=45
+NUM_TESTS=49
 
 source $TESTDIR/utils/utils.sh
 
@@ -40,11 +41,11 @@  function run_app()
 
 function test_ust_implicit_no_blocking()
 {
-	NUM_EVENT=500000
+	NUM_EVENT=5000000
 	diag "UST implicit non-blocking mode (default): will hang if fails"
 
-	# Test without the plugin
 	start_lttng_sessiond
+	# session in no-output mode
 	create_lttng_session_no_output $SESSION_NAME
 	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
 	start_lttng_tracing_ok $SESSION_NAME
@@ -56,17 +57,18 @@  function test_ust_implicit_no_blocking()
 	ok 0 "Does not hang"
 }
 
-function test_ust_explicit_no_blocking()
+function test_ust_implicit_no_blocking_with_channel_blocking()
 {
-	NUM_EVENT=500000
-	diag "UST explicit non-blocking mode: will hang if fails"
+	NUM_EVENT=5000000
+	diag "UST implicit non-blocking mode (default) with blocking-timeout=-1 channel: will hang if fails"
 
-	# Test without the plugin
 	start_lttng_sessiond
+	# session in no-output mode
 	create_lttng_session_no_output $SESSION_NAME
-	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
+	enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=-1"
+	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
 	start_lttng_tracing_ok $SESSION_NAME
-	LTTNG_UST_BLOCKING_RETRY_TIMEOUT=0 run_app
+	run_app
 	stop_lttng_tracing_ok $SESSION_NAME
 	destroy_lttng_session_ok $SESSION_NAME
 	stop_lttng_sessiond
@@ -77,14 +79,16 @@  function test_ust_explicit_no_blocking()
 function test_ust_timeout_no_blocking()
 {
 	NUM_EVENT=12500
-	diag "UST 1ms timeout retry mode: will hang if fails"
+	diag "UST 1ms timeout blocking mode: will hang if fails"
 
 	start_lttng_sessiond
+	# session in no-output mode
 	create_lttng_session_no_output $SESSION_NAME
-	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
+	# blocking timeout 1ms
+	enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=1000"
+	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
 	start_lttng_tracing_ok $SESSION_NAME
-	# retry timeout 1ms
-	LTTNG_UST_BLOCKING_RETRY_TIMEOUT=1 run_app
+	LTTNG_UST_ALLOW_BLOCKING=1 run_app
 	stop_lttng_tracing_ok $SESSION_NAME
 	destroy_lttng_session_ok $SESSION_NAME
 	stop_lttng_sessiond
@@ -94,15 +98,17 @@  function test_ust_timeout_no_blocking()
 
 function test_ust_snapshot_no_blocking()
 {
-	NUM_EVENT=500000
+	NUM_EVENT=5000000
 	diag "UST blocking mode: don't block in snapshot mode"
 
 	# Test without the plugin
 	start_lttng_sessiond
 	create_lttng_session_ok $SESSION_NAME $TRACE_PATH --snapshot
-	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
+	# blocking timeout 1ms
+	enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=1000"
+	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
 	start_lttng_tracing_ok $SESSION_NAME
-	LTTNG_UST_BLOCKING_RETRY_TIMEOUT=-1 run_app
+	LTTNG_UST_ALLOW_BLOCKING=1 run_app
 	stop_lttng_tracing_ok $SESSION_NAME
 	destroy_lttng_session_ok $SESSION_NAME
 	stop_lttng_sessiond
@@ -112,16 +118,17 @@  function test_ust_snapshot_no_blocking()
 
 function test_ust_blocking_no_discard()
 {
-	NUM_EVENT=500000
+	NUM_EVENT=5000000
 	diag "UST blocking mode: no event discarded"
 
 	# Test without the plugin
 	start_lttng_sessiond
 	create_lttng_session_ok $SESSION_NAME $TRACE_PATH
-	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME"
+	# infinite blocking timeout
+	enable_ust_lttng_channel_ok $SESSION_NAME $CHANNEL_NAME "--blocking-timeout=-1"
+	enable_ust_lttng_event_ok $SESSION_NAME "$EVENT_NAME" $CHANNEL_NAME
 	start_lttng_tracing_ok $SESSION_NAME
-	# infinite retry timeout
-	LTTNG_UST_BLOCKING_RETRY_TIMEOUT=-1 run_app
+	LTTNG_UST_ALLOW_BLOCKING=1 run_app
 	stop_lttng_tracing_ok $SESSION_NAME
 	destroy_lttng_session_ok $SESSION_NAME
 	stop_lttng_sessiond
@@ -138,7 +145,7 @@  print_test_banner "$TEST_DESC"
 
 TESTS=(
 	"test_ust_implicit_no_blocking"
-	"test_ust_explicit_no_blocking"
+	"test_ust_implicit_no_blocking_with_channel_blocking"
 	"test_ust_timeout_no_blocking"
 	"test_ust_snapshot_no_blocking"
 	"test_ust_blocking_no_discard"