[lttng-dev] [PATCH lttng-tools v2] Fix: timeout for connect is not respected

2018-11-09 Thread Jonathan Rajotte
Problem:

The previous algorithm was not *wrong* but was prone to C type conversion
error.

Previous algorithm:

((A.sec - B.sec) * MSEC_PER_SEC) + ((A.nsec - B.nsec) / NSEC_PER_SEC)

((A.sec - B.sec) * 100ULL) + ((A.nsec - B.nsec) / 100ULL)

Note that "(A.nsec - B.nsec)" can be negative.

A *quick* fix here could be to cast the NSEC_PER_SEC to long allowing a
valid division operation.

The problem was introduced by 395d6b02dda3db1acd08936f49c1dc8efc48e613.

Solution:

Perform the time diff using a temporary timespec struct and perform the
carry operation manually. This prevent negative value for nsec and 
helps prevent C type promotion problems.

Signed-off-by: Jonathan Rajotte 
---

I initially misplaced the issue.
As mentioned in the commit message, we can also cast NSEC_PER_SEC to long to fix
the issue. I prefer the use of a timespec struct for expressiveness.

Also the case were we pass a time_b > time_a is handled by returning a
difference of zero. We might want to assert here since it should never happen.

 src/common/sessiond-comm/inet.c  | 28 
 src/common/sessiond-comm/inet6.c | 28 
 2 files changed, 40 insertions(+), 16 deletions(-)

diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c
index e0b3e7a96..94a3c3a67 100644
--- a/src/common/sessiond-comm/inet.c
+++ b/src/common/sessiond-comm/inet.c
@@ -119,16 +119,28 @@ static
 unsigned long time_diff_ms(struct timespec *time_a,
struct timespec *time_b)
 {
-   time_t sec_diff;
-   long nsec_diff;
-   unsigned long result_ms;
+   struct timespec diff;
 
-   sec_diff = time_a->tv_sec - time_b->tv_sec;
-   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
+   diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
+   diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
 
-   result_ms = sec_diff * MSEC_PER_SEC;
-   result_ms += nsec_diff / NSEC_PER_MSEC;
-   return result_ms;
+   if (diff.tv_nsec < 0) {
+   /* Perform borrow operation */
+   diff.tv_sec -= 1;
+   diff.tv_nsec += NSEC_PER_SEC;
+   }
+
+   if (diff.tv_sec < 0) {
+   /* We went back in time. Put all to zero */
+   diff.tv_sec = 0;
+   diff.tv_nsec = 0;
+   }
+
+   /*
+* Transform into MSEC, diff.tv_nsec is always positive due to borrow
+* operation. diff.tb_sec is always positive.
+*/
+   return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
 }
 
 static
diff --git a/src/common/sessiond-comm/inet6.c b/src/common/sessiond-comm/inet6.c
index dfb5fc5d1..07043e93f 100644
--- a/src/common/sessiond-comm/inet6.c
+++ b/src/common/sessiond-comm/inet6.c
@@ -117,16 +117,28 @@ static
 unsigned long time_diff_ms(struct timespec *time_a,
struct timespec *time_b)
 {
-   time_t sec_diff;
-   long nsec_diff;
-   unsigned long result_ms;
+   struct timespec diff;
 
-   sec_diff = time_a->tv_sec - time_b->tv_sec;
-   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
+   diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
+   diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
 
-   result_ms = sec_diff * MSEC_PER_SEC;
-   result_ms += nsec_diff / NSEC_PER_MSEC;
-   return result_ms;
+   if (diff.tv_nsec < 0) {
+   /* Perform borrow operation */
+   diff.tv_sec -= 1;
+   diff.tv_nsec += NSEC_PER_SEC;
+   }
+
+   if (diff.tv_sec < 0) {
+   /* We went back in time. Put all to zero */
+   diff.tv_sec = 0;
+   diff.tv_nsec = 0;
+   }
+
+   /*
+* Transform into MSEC, diff.tv_nsec is always positive due to borrow
+* operation. diff.tb_sec is always positive.
+*/
+   return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
 }
 
 static
-- 
2.17.1

___
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev


Re: [lttng-dev] [PATCH lttng-tools v2] Fix: timeout for connect is not respected

2018-11-09 Thread Mathieu Desnoyers
- On Nov 9, 2018, at 10:37 AM, Jonathan Rajotte 
jonathan.rajotte-jul...@efficios.com wrote:

> Problem:
> 
> The previous algorithm was not *wrong* but was prone to C type conversion
> error.
> 
> Previous algorithm:
> 
> ((A.sec - B.sec) * MSEC_PER_SEC) + ((A.nsec - B.nsec) / NSEC_PER_SEC)
> 
> ((A.sec - B.sec) * 100ULL) + ((A.nsec - B.nsec) / 100ULL)
> 
> Note that "(A.nsec - B.nsec)" can be negative.
> 
> A *quick* fix here could be to cast the NSEC_PER_SEC to long allowing a
> valid division operation.
> 
> The problem was introduced by 395d6b02dda3db1acd08936f49c1dc8efc48e613.
> 
> Solution:
> 
> Perform the time diff using a temporary timespec struct and perform the
> carry operation manually. This prevent negative value for nsec and
> helps prevent C type promotion problems.
> 
> Signed-off-by: Jonathan Rajotte 
> ---
> 
> I initially misplaced the issue.
> As mentioned in the commit message, we can also cast NSEC_PER_SEC to long to 
> fix
> the issue. I prefer the use of a timespec struct for expressiveness.
> 
> Also the case were we pass a time_b > time_a is handled by returning a
> difference of zero. We might want to assert here since it should never happen.
> 
> src/common/sessiond-comm/inet.c  | 28 
> src/common/sessiond-comm/inet6.c | 28 
> 2 files changed, 40 insertions(+), 16 deletions(-)
> 
> diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c
> index e0b3e7a96..94a3c3a67 100644
> --- a/src/common/sessiond-comm/inet.c
> +++ b/src/common/sessiond-comm/inet.c
> @@ -119,16 +119,28 @@ static
> unsigned long time_diff_ms(struct timespec *time_a,
>   struct timespec *time_b)
> {
> - time_t sec_diff;
> - long nsec_diff;
> - unsigned long result_ms;
> + struct timespec diff;
> 
> - sec_diff = time_a->tv_sec - time_b->tv_sec;
> - nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
> + diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
> + diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
> 
> - result_ms = sec_diff * MSEC_PER_SEC;
> - result_ms += nsec_diff / NSEC_PER_MSEC;
> - return result_ms;
> + if (diff.tv_nsec < 0) {
> + /* Perform borrow operation */
> + diff.tv_sec -= 1;
> + diff.tv_nsec += NSEC_PER_SEC;
> + }
> +
> + if (diff.tv_sec < 0) {
> + /* We went back in time. Put all to zero */
> + diff.tv_sec = 0;
> + diff.tv_nsec = 0;
> + }

Why would a diff operation implicitly floor everything to 0 when
time_a < time_b ?

> +
> + /*
> +  * Transform into MSEC, diff.tv_nsec is always positive due to borrow
> +  * operation. diff.tb_sec is always positive.

tb_sec -> tv_nsec


> +  */
> + return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);

How do we handle time delta difference that overflows unsigned long ?

> }
> 
> static
> diff --git a/src/common/sessiond-comm/inet6.c 
> b/src/common/sessiond-comm/inet6.c
> index dfb5fc5d1..07043e93f 100644
> --- a/src/common/sessiond-comm/inet6.c
> +++ b/src/common/sessiond-comm/inet6.c
> @@ -117,16 +117,28 @@ static
> unsigned long time_diff_ms(struct timespec *time_a,
>   struct timespec *time_b)

This should be moved to a common implementation file. It's a cut and
paste from inet.c.

Thanks,

Mathieu

> {
> - time_t sec_diff;
> - long nsec_diff;
> - unsigned long result_ms;
> + struct timespec diff;
> 
> - sec_diff = time_a->tv_sec - time_b->tv_sec;
> - nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
> + diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
> + diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
> 
> - result_ms = sec_diff * MSEC_PER_SEC;
> - result_ms += nsec_diff / NSEC_PER_MSEC;
> - return result_ms;
> + if (diff.tv_nsec < 0) {
> + /* Perform borrow operation */
> + diff.tv_sec -= 1;
> + diff.tv_nsec += NSEC_PER_SEC;
> + }
> +
> + if (diff.tv_sec < 0) {
> + /* We went back in time. Put all to zero */
> + diff.tv_sec = 0;
> + diff.tv_nsec = 0;
> + }
> +
> + /*
> +  * Transform into MSEC, diff.tv_nsec is always positive due to borrow
> +  * operation. diff.tb_sec is always positive.
> +  */
> + return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
> }
> 
> static
> --
> 2.17.1
> 
> ___
> lttng-dev mailing list
> lttng-dev@lists.lttng.org
> https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
___
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev


Re: [lttng-dev] [PATCH lttng-tools v2] Fix: timeout for connect is not respected

2018-11-09 Thread Jonathan Rajotte-Julien
> > diff --git a/src/common/sessiond-comm/inet.c 
> > b/src/common/sessiond-comm/inet.c
> > index e0b3e7a96..94a3c3a67 100644
> > --- a/src/common/sessiond-comm/inet.c
> > +++ b/src/common/sessiond-comm/inet.c
> > @@ -119,16 +119,28 @@ static
> > unsigned long time_diff_ms(struct timespec *time_a,
> > struct timespec *time_b)
> > {
> > -   time_t sec_diff;
> > -   long nsec_diff;
> > -   unsigned long result_ms;
> > +   struct timespec diff;
> > 
> > -   sec_diff = time_a->tv_sec - time_b->tv_sec;
> > -   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
> > +   diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
> > +   diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
> > 
> > -   result_ms = sec_diff * MSEC_PER_SEC;
> > -   result_ms += nsec_diff / NSEC_PER_MSEC;
> > -   return result_ms;
> > +   if (diff.tv_nsec < 0) {
> > +   /* Perform borrow operation */
> > +   diff.tv_sec -= 1;
> > +   diff.tv_nsec += NSEC_PER_SEC;
> > +   }
> > +
> > +   if (diff.tv_sec < 0) {
> > +   /* We went back in time. Put all to zero */
> > +   diff.tv_sec = 0;
> > +   diff.tv_nsec = 0;
> > +   }
> 
> Why would a diff operation implicitly floor everything to 0 when
> time_a < time_b ?

Sure I can implement it as a real difference without the same "assumptions" of
time_a > time_b since we are comparing passing time.

Make sure to tell this to past Mathieu ;).

> 
> > +
> > +   /*
> > +* Transform into MSEC, diff.tv_nsec is always positive due to borrow
> > +* operation. diff.tb_sec is always positive.
> 
> tb_sec -> tv_nsec

Fixed.

> 
> 
> > +*/
> > +   return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
> 
> How do we handle time delta difference that overflows unsigned long ?

Let's do a quick calculation. Correct me if anything is wrong here.

How many msec does a unsigned long hold?
A long is *minimum* 32 bits. Yielding a maximum value of 4294967295. [1]

Lets assume that the nanoseconds part of the diff struct is maxed out. The
nanoseconds part yield 99 ms.

4294967295 - 99 = 4294967196ms

How big would the second field of diff be a problem?

4294967196/ MSEC_PER_SEC = 4294967s or 49 days.

I would err on the side of "that it's enough". We also have to take into
account that for this to happen either something is going horribly wrong during
getting the current time or the user purposely set the timeout to this value
since we sample every 200ms.
Which at this point goes into the PEBKAC category.

Do you agree?

[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf p.22 §5.2.4.2.1

> 
> > }
> > 
> > static
> > diff --git a/src/common/sessiond-comm/inet6.c 
> > b/src/common/sessiond-comm/inet6.c
> > index dfb5fc5d1..07043e93f 100644
> > --- a/src/common/sessiond-comm/inet6.c
> > +++ b/src/common/sessiond-comm/inet6.c
> > @@ -117,16 +117,28 @@ static
> > unsigned long time_diff_ms(struct timespec *time_a,
> > struct timespec *time_b)
> 
> This should be moved to a common implementation file. It's a cut and
> paste from inet.c.

Past Mathieu did not seems to bother here.

I'm open into doing this in two patches since this should be backported. Do you
have a suggestion regarding where to put it?

> 
> Thanks,
> 
> Mathieu
> 
> > {
> > -   time_t sec_diff;
> > -   long nsec_diff;
> > -   unsigned long result_ms;
> > +   struct timespec diff;
> > 
> > -   sec_diff = time_a->tv_sec - time_b->tv_sec;
> > -   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
> > +   diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
> > +   diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
> > 
> > -   result_ms = sec_diff * MSEC_PER_SEC;
> > -   result_ms += nsec_diff / NSEC_PER_MSEC;
> > -   return result_ms;
> > +   if (diff.tv_nsec < 0) {
> > +   /* Perform borrow operation */
> > +   diff.tv_sec -= 1;
> > +   diff.tv_nsec += NSEC_PER_SEC;
> > +   }
> > +
> > +   if (diff.tv_sec < 0) {
> > +   /* We went back in time. Put all to zero */
> > +   diff.tv_sec = 0;
> > +   diff.tv_nsec = 0;
> > +   }
> > +
> > +   /*
> > +* Transform into MSEC, diff.tv_nsec is always positive due to borrow
> > +* operation. diff.tb_sec is always positive.
> > +*/
> > +   return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
> > }
> > 
> > static
> > --
> > 2.17.1
> > 
> > ___
> > lttng-dev mailing list
> > lttng-dev@lists.lttng.org
> > https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
> 
> -- 
> Mathieu Desnoyers
> EfficiOS Inc.
> http://www.efficios.com

-- 
Jonathan Rajotte-Julien
EfficiOS
___
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev


[lttng-dev] [PATCH lttng-tools v3] Fix: timeout for connect is not respected

2018-11-09 Thread Jonathan Rajotte
Problem:

The previous algorithm was not *wrong* but was prone to C type conversion
error.

Previous algorithm:

((A.sec - B.sec) * MSEC_PER_SEC) + ((A.nsec - B.nsec) / NSEC_PER_SEC)

((A.sec - B.sec) * 100ULL) + ((A.nsec - B.nsec) / 100ULL)

Note that "(A.nsec - B.nsec)" can be negative.

A *quick* fix here is to cast the NSEC_PER_SEC to long allowing a valid
division operation.

The problem was introduced by 395d6b02dda3db1acd08936f49c1dc8efc48e613.

Solution:

Perform the time diff using a temporary timespec struct and perform the
carry operation manually. This prevent negative value for nsec and help
prevent C type promotion problems.

Signed-off-by: Jonathan Rajotte 
---

Implement difference without posing the hypothesis that time_a is necessarily
bigger than time_b.

Fixed type in comment.

Added an assert statement to ensure premises before returning. Feel free to
remove.

 src/common/sessiond-comm/inet.c  | 32 
 src/common/sessiond-comm/inet6.c | 32 
 2 files changed, 48 insertions(+), 16 deletions(-)

diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c
index e0b3e7a96..f03fd1fb5 100644
--- a/src/common/sessiond-comm/inet.c
+++ b/src/common/sessiond-comm/inet.c
@@ -119,16 +119,32 @@ static
 unsigned long time_diff_ms(struct timespec *time_a,
struct timespec *time_b)
 {
-   time_t sec_diff;
-   long nsec_diff;
-   unsigned long result_ms;
+   struct timespec diff;
 
-   sec_diff = time_a->tv_sec - time_b->tv_sec;
-   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
+   if ((time_a->tv_sec > time_b->tv_sec)
+   || ((time_a->tv_sec == time_b->tv_sec)
+   && (time_a->tv_nsec > time_b->tv_nsec))) {
+   /* time_a is bigger */
+   diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
+   diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
+   } else {
+   /* time_b is bigger */
+   diff.tv_sec = time_b->tv_sec - time_a->tv_sec;
+   diff.tv_nsec = time_b->tv_nsec - time_a->tv_nsec;
+   }
 
-   result_ms = sec_diff * MSEC_PER_SEC;
-   result_ms += nsec_diff / NSEC_PER_MSEC;
-   return result_ms;
+   if (diff.tv_nsec < 0) {
+   /* Perform borrow operation */
+   diff.tv_sec -= 1;
+   diff.tv_nsec += NSEC_PER_SEC;
+   }
+
+   /*
+* Transform into MSEC, diff.tv_nsec is always positive due to borrow
+* operation. diff.tv_sec is always positive.
+*/
+   assert(diff.tv_sec >= 0 && diff.tv_nsec >= 0);
+   return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
 }
 
 static
diff --git a/src/common/sessiond-comm/inet6.c b/src/common/sessiond-comm/inet6.c
index dfb5fc5d1..beb2dd9ed 100644
--- a/src/common/sessiond-comm/inet6.c
+++ b/src/common/sessiond-comm/inet6.c
@@ -117,16 +117,32 @@ static
 unsigned long time_diff_ms(struct timespec *time_a,
struct timespec *time_b)
 {
-   time_t sec_diff;
-   long nsec_diff;
-   unsigned long result_ms;
+   struct timespec diff;
 
-   sec_diff = time_a->tv_sec - time_b->tv_sec;
-   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
+   if ((time_a->tv_sec > time_b->tv_sec)
+   || ((time_a->tv_sec == time_b->tv_sec)
+   && (time_a->tv_nsec > time_b->tv_nsec))) {
+   /* time_a is bigger */
+   diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
+   diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
+   } else {
+   /* time_b is bigger */
+   diff.tv_sec = time_b->tv_sec - time_a->tv_sec;
+   diff.tv_nsec = time_b->tv_nsec - time_a->tv_nsec;
+   }
 
-   result_ms = sec_diff * MSEC_PER_SEC;
-   result_ms += nsec_diff / NSEC_PER_MSEC;
-   return result_ms;
+   if (diff.tv_nsec < 0) {
+   /* Perform borrow operation */
+   diff.tv_sec -= 1;
+   diff.tv_nsec += NSEC_PER_SEC;
+   }
+
+   /*
+* Transform into MSEC, diff.tv_nsec is always positive due to borrow
+* operation. diff.tv_sec is always positive.
+*/
+   assert(diff.tv_sec >= 0 && diff.tv_nsec >= 0);
+   return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
 }
 
 static
-- 
2.17.1

___
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev


Re: [lttng-dev] [PATCH lttng-tools v2] Fix: timeout for connect is not respected

2018-11-09 Thread Mathieu Desnoyers
- On Nov 9, 2018, at 1:52 PM, Jonathan Rajotte 
jonathan.rajotte-jul...@efficios.com wrote:

>> > diff --git a/src/common/sessiond-comm/inet.c 
>> > b/src/common/sessiond-comm/inet.c
>> > index e0b3e7a96..94a3c3a67 100644
>> > --- a/src/common/sessiond-comm/inet.c
>> > +++ b/src/common/sessiond-comm/inet.c
>> > @@ -119,16 +119,28 @@ static
>> > unsigned long time_diff_ms(struct timespec *time_a,
>> >struct timespec *time_b)
>> > {
>> > -  time_t sec_diff;
>> > -  long nsec_diff;
>> > -  unsigned long result_ms;
>> > +  struct timespec diff;
>> > 
>> > -  sec_diff = time_a->tv_sec - time_b->tv_sec;
>> > -  nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
>> > +  diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
>> > +  diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
>> > 
>> > -  result_ms = sec_diff * MSEC_PER_SEC;
>> > -  result_ms += nsec_diff / NSEC_PER_MSEC;
>> > -  return result_ms;
>> > +  if (diff.tv_nsec < 0) {
>> > +  /* Perform borrow operation */
>> > +  diff.tv_sec -= 1;
>> > +  diff.tv_nsec += NSEC_PER_SEC;
>> > +  }
>> > +
>> > +  if (diff.tv_sec < 0) {
>> > +  /* We went back in time. Put all to zero */
>> > +  diff.tv_sec = 0;
>> > +  diff.tv_nsec = 0;
>> > +  }
>> 
>> Why would a diff operation implicitly floor everything to 0 when
>> time_a < time_b ?
> 
> Sure I can implement it as a real difference without the same "assumptions" of
> time_a > time_b since we are comparing passing time.
> 
> Make sure to tell this to past Mathieu ;).

I'll try, as soon as I find a time machine :)

> 
>> 
>> > +
>> > +  /*
>> > +   * Transform into MSEC, diff.tv_nsec is always positive due to borrow
>> > +   * operation. diff.tb_sec is always positive.
>> 
>> tb_sec -> tv_nsec
> 
> Fixed.
> 
>> 
>> 
>> > +   */
>> > +  return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
>> 
>> How do we handle time delta difference that overflows unsigned long ?
> 
> Let's do a quick calculation. Correct me if anything is wrong here.
> 
> How many msec does a unsigned long hold?
> A long is *minimum* 32 bits. Yielding a maximum value of 4294967295. [1]
> 
> Lets assume that the nanoseconds part of the diff struct is maxed out. The
> nanoseconds part yield 99 ms.
> 
> 4294967295 - 99 = 4294967196ms
> 
> How big would the second field of diff be a problem?
> 
> 4294967196/ MSEC_PER_SEC = 4294967s or 49 days.
> 
> I would err on the side of "that it's enough". We also have to take into
> account that for this to happen either something is going horribly wrong 
> during
> getting the current time or the user purposely set the timeout to this value
> since we sample every 200ms.
> Which at this point goes into the PEBKAC category.
> 
> Do you agree?

It would be cleaner to return the result in an output parameter, return 0 on 
success,
negative error on error, and check for errors in the caller.

Thus, we can figure out if the result end up overflowing unsigned long, and 
return
an error accordingly.

Thanks,

Mathieu


> 
> [1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf p.22 §5.2.4.2.1
> 
>> 
>> > }
>> > 
>> > static
>> > diff --git a/src/common/sessiond-comm/inet6.c 
>> > b/src/common/sessiond-comm/inet6.c
>> > index dfb5fc5d1..07043e93f 100644
>> > --- a/src/common/sessiond-comm/inet6.c
>> > +++ b/src/common/sessiond-comm/inet6.c
>> > @@ -117,16 +117,28 @@ static
>> > unsigned long time_diff_ms(struct timespec *time_a,
>> >struct timespec *time_b)
>> 
>> This should be moved to a common implementation file. It's a cut and
>> paste from inet.c.
> 
> Past Mathieu did not seems to bother here.
> 
> I'm open into doing this in two patches since this should be backported. Do 
> you
> have a suggestion regarding where to put it?
> 
>> 
>> Thanks,
>> 
>> Mathieu
>> 
>> > {
>> > -  time_t sec_diff;
>> > -  long nsec_diff;
>> > -  unsigned long result_ms;
>> > +  struct timespec diff;
>> > 
>> > -  sec_diff = time_a->tv_sec - time_b->tv_sec;
>> > -  nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
>> > +  diff.tv_sec = time_a->tv_sec - time_b->tv_sec;
>> > +  diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec;
>> > 
>> > -  result_ms = sec_diff * MSEC_PER_SEC;
>> > -  result_ms += nsec_diff / NSEC_PER_MSEC;
>> > -  return result_ms;
>> > +  if (diff.tv_nsec < 0) {
>> > +  /* Perform borrow operation */
>> > +  diff.tv_sec -= 1;
>> > +  diff.tv_nsec += NSEC_PER_SEC;
>> > +  }
>> > +
>> > +  if (diff.tv_sec < 0) {
>> > +  /* We went back in time. Put all to zero */
>> > +  diff.tv_sec = 0;
>> > +  diff.tv_nsec = 0;
>> > +  }
>> > +
>> > +  /*
>> > +   * Transform into MSEC, diff.tv_nsec is always positive due to borrow
>> > +   * operation. diff.tb_sec is always positive.
>> > +   */
>> > +  return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC);
>> > }
>> > 
>> > static
>> > --
>> > 2.17.1
>> > 
>> > ___
>> > lttng-dev mailing li

[lttng-dev] [PATCH lttng-tools 2/2] Fix: max_t/min_t macros are missing cast on input

2018-11-09 Thread Mathieu Desnoyers
The semantic expected from max_t and min_t is to perform the max/min
comparison in the type provided as first parameter.

Cast the input parameters to the proper type before comparing them,
rather than after. There is no more need to cast the result of the
expression now that both inputs are cast to the right type.

Signed-off-by: Mathieu Desnoyers 
---
 src/common/macros.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/common/macros.h b/src/common/macros.h
index c521aacd..461202ff 100644
--- a/src/common/macros.h
+++ b/src/common/macros.h
@@ -72,7 +72,7 @@ void *zmalloc(size_t len)
 #endif
 
 #ifndef max_t
-#define max_t(type, a, b)  ((type) max(a, b))
+#define max_t(type, a, b)  max((type) a, (type) b)
 #endif
 
 #ifndef min
@@ -80,7 +80,7 @@ void *zmalloc(size_t len)
 #endif
 
 #ifndef min_t
-#define min_t(type, a, b)  ((type) min(a, b))
+#define min_t(type, a, b)  min((type) a, (type) b)
 #endif
 
 #ifndef LTTNG_PACKED
-- 
2.11.0

___
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev


[lttng-dev] [PATCH lttng-tools 1/2] Fix: Connect timeout arithmetic in inet/inet6

2018-11-09 Thread Mathieu Desnoyers
The nanoseconds part of the timespec struct time_a is not always
bigger than time_b since it wrap around each seconds.

Use 64-bit arithmetic to perform the difference.

Merge/move duplicated code into utils.c.

This function is really doing two things. Split it into timespec_to_ms()
and timespec_abs_diff().

Signed-off-by: Mathieu Desnoyers 
---
 src/common/common.h  |  5 +
 src/common/sessiond-comm/inet.c  | 28 
 src/common/sessiond-comm/inet6.c | 28 
 src/common/utils.c   | 29 +
 4 files changed, 50 insertions(+), 40 deletions(-)

diff --git a/src/common/common.h b/src/common/common.h
index 41eb0361..48f39e0e 100644
--- a/src/common/common.h
+++ b/src/common/common.h
@@ -19,9 +19,14 @@
 #ifndef _COMMON_H
 #define _COMMON_H
 
+#include 
+
 #include "error.h"
 #include "macros.h"
 #include "runas.h"
 #include "readwrite.h"
 
+int timespec_to_ms(struct timespec ts, unsigned long *ms);
+struct timespec timespec_abs_diff(struct timespec ts_a, struct timespec ts_b);
+
 #endif /* _COMMON_H */
diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c
index e0b3e7a9..76a3b7ff 100644
--- a/src/common/sessiond-comm/inet.c
+++ b/src/common/sessiond-comm/inet.c
@@ -112,31 +112,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
sizeof(sock->sockaddr.addr.sin));
 }
 
-/*
- * Return time_a - time_b  in milliseconds.
- */
-static
-unsigned long time_diff_ms(struct timespec *time_a,
-   struct timespec *time_b)
-{
-   time_t sec_diff;
-   long nsec_diff;
-   unsigned long result_ms;
-
-   sec_diff = time_a->tv_sec - time_b->tv_sec;
-   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
-
-   result_ms = sec_diff * MSEC_PER_SEC;
-   result_ms += nsec_diff / NSEC_PER_MSEC;
-   return result_ms;
-}
-
 static
 int connect_with_timeout(struct lttcomm_sock *sock)
 {
unsigned long timeout = lttcomm_get_network_timeout();
int ret, flags, connect_ret;
struct timespec orig_time, cur_time;
+   unsigned long diff_ms;
 
ret = fcntl(sock->fd, F_GETFL, 0);
if (ret == -1) {
@@ -217,7 +199,13 @@ int connect_with_timeout(struct lttcomm_sock *sock)
connect_ret = ret;
goto error;
}
-   } while (time_diff_ms(&cur_time, &orig_time) < timeout);
+   if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time), 
&diff_ms) < 0) {
+   ERR("timespec_to_ms input overflows milliseconds 
output");
+   errno = EOVERFLOW;
+   connect_ret = -1;
+   goto error;
+   }
+   } while (diff_ms < timeout);
 
/* Timeout */
errno = ETIMEDOUT;
diff --git a/src/common/sessiond-comm/inet6.c b/src/common/sessiond-comm/inet6.c
index dfb5fc5d..5c1ac2e0 100644
--- a/src/common/sessiond-comm/inet6.c
+++ b/src/common/sessiond-comm/inet6.c
@@ -110,31 +110,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
sizeof(sock->sockaddr.addr.sin6));
 }
 
-/*
- * Return time_a - time_b  in milliseconds.
- */
-static
-unsigned long time_diff_ms(struct timespec *time_a,
-   struct timespec *time_b)
-{
-   time_t sec_diff;
-   long nsec_diff;
-   unsigned long result_ms;
-
-   sec_diff = time_a->tv_sec - time_b->tv_sec;
-   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
-
-   result_ms = sec_diff * MSEC_PER_SEC;
-   result_ms += nsec_diff / NSEC_PER_MSEC;
-   return result_ms;
-}
-
 static
 int connect_with_timeout(struct lttcomm_sock *sock)
 {
unsigned long timeout = lttcomm_get_network_timeout();
int ret, flags, connect_ret;
struct timespec orig_time, cur_time;
+   unsigned long diff_ms;
 
ret = fcntl(sock->fd, F_GETFL, 0);
if (ret == -1) {
@@ -216,7 +198,13 @@ int connect_with_timeout(struct lttcomm_sock *sock)
connect_ret = ret;
goto error;
}
-   } while (time_diff_ms(&cur_time, &orig_time) < timeout);
+   if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time), 
&diff_ms) < 0) {
+   ERR("timespec_to_ms input overflows milliseconds 
output");
+   errno = EOVERFLOW;
+   connect_ret = -1;
+   goto error;
+   }
+   } while (diff_ms < timeout);
 
/* Timeout */
errno = ETIMEDOUT;
diff --git a/src/common/utils.c b/src/common/utils.c
index 3442bef8..c4759f68 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -41,6 +42,7 @@
 
 #include "utils.h"
 #include "defaults.h"
+#include "time.h"
 
 /*
  * Return a partial realpath(3) of the path even if the full path does not

Re: [lttng-dev] [PATCH lttng-tools 1/2] Fix: Connect timeout arithmetic in inet/inet6

2018-11-09 Thread Jonathan Rajotte-Julien
On Fri, Nov 09, 2018 at 05:27:48PM -0500, Mathieu Desnoyers wrote:
> The nanoseconds part of the timespec struct time_a is not always
> bigger than time_b since it wrap around each seconds.
> 
> Use 64-bit arithmetic to perform the difference.
> 
> Merge/move duplicated code into utils.c.
> 
> This function is really doing two things. Split it into timespec_to_ms()
> and timespec_abs_diff().
> 
> Signed-off-by: Mathieu Desnoyers 
> ---
>  src/common/common.h  |  5 +
>  src/common/sessiond-comm/inet.c  | 28 
>  src/common/sessiond-comm/inet6.c | 28 
>  src/common/utils.c   | 29 +
>  4 files changed, 50 insertions(+), 40 deletions(-)
> 
> diff --git a/src/common/common.h b/src/common/common.h
> index 41eb0361..48f39e0e 100644
> --- a/src/common/common.h
> +++ b/src/common/common.h
> @@ -19,9 +19,14 @@
>  #ifndef _COMMON_H
>  #define _COMMON_H
>  
> +#include 
> +
>  #include "error.h"
>  #include "macros.h"
>  #include "runas.h"
>  #include "readwrite.h"
>  
> +int timespec_to_ms(struct timespec ts, unsigned long *ms);
> +struct timespec timespec_abs_diff(struct timespec ts_a, struct timespec 
> ts_b);
> +
>  #endif /* _COMMON_H */
> diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c
> index e0b3e7a9..76a3b7ff 100644
> --- a/src/common/sessiond-comm/inet.c
> +++ b/src/common/sessiond-comm/inet.c
> @@ -112,31 +112,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
>   sizeof(sock->sockaddr.addr.sin));
>  }
>  
> -/*
> - * Return time_a - time_b  in milliseconds.
> - */
> -static
> -unsigned long time_diff_ms(struct timespec *time_a,
> - struct timespec *time_b)
> -{
> - time_t sec_diff;
> - long nsec_diff;
> - unsigned long result_ms;
> -
> - sec_diff = time_a->tv_sec - time_b->tv_sec;
> - nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
> -
> - result_ms = sec_diff * MSEC_PER_SEC;
> - result_ms += nsec_diff / NSEC_PER_MSEC;
> - return result_ms;
> -}
> -
>  static
>  int connect_with_timeout(struct lttcomm_sock *sock)
>  {
>   unsigned long timeout = lttcomm_get_network_timeout();
>   int ret, flags, connect_ret;
>   struct timespec orig_time, cur_time;
> + unsigned long diff_ms;
>  
>   ret = fcntl(sock->fd, F_GETFL, 0);
>   if (ret == -1) {
> @@ -217,7 +199,13 @@ int connect_with_timeout(struct lttcomm_sock *sock)
>   connect_ret = ret;
>   goto error;
>   }
> - } while (time_diff_ms(&cur_time, &orig_time) < timeout);
> + if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time), 
> &diff_ms) < 0) {
> + ERR("timespec_to_ms input overflows milliseconds 
> output");
> + errno = EOVERFLOW;
> + connect_ret = -1;
> + goto error;
> + }
> + } while (diff_ms < timeout);
>  
>   /* Timeout */
>   errno = ETIMEDOUT;
> diff --git a/src/common/sessiond-comm/inet6.c 
> b/src/common/sessiond-comm/inet6.c
> index dfb5fc5d..5c1ac2e0 100644
> --- a/src/common/sessiond-comm/inet6.c
> +++ b/src/common/sessiond-comm/inet6.c
> @@ -110,31 +110,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
>   sizeof(sock->sockaddr.addr.sin6));
>  }
>  
> -/*
> - * Return time_a - time_b  in milliseconds.
> - */
> -static
> -unsigned long time_diff_ms(struct timespec *time_a,
> - struct timespec *time_b)
> -{
> - time_t sec_diff;
> - long nsec_diff;
> - unsigned long result_ms;
> -
> - sec_diff = time_a->tv_sec - time_b->tv_sec;
> - nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
> -
> - result_ms = sec_diff * MSEC_PER_SEC;
> - result_ms += nsec_diff / NSEC_PER_MSEC;
> - return result_ms;
> -}
> -
>  static
>  int connect_with_timeout(struct lttcomm_sock *sock)
>  {
>   unsigned long timeout = lttcomm_get_network_timeout();
>   int ret, flags, connect_ret;
>   struct timespec orig_time, cur_time;
> + unsigned long diff_ms;
>  
>   ret = fcntl(sock->fd, F_GETFL, 0);
>   if (ret == -1) {
> @@ -216,7 +198,13 @@ int connect_with_timeout(struct lttcomm_sock *sock)
>   connect_ret = ret;
>   goto error;
>   }
> - } while (time_diff_ms(&cur_time, &orig_time) < timeout);
> + if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time), 
> &diff_ms) < 0) {
> + ERR("timespec_to_ms input overflows milliseconds 
> output");
> + errno = EOVERFLOW;
> + connect_ret = -1;
> + goto error;
> + }
> + } while (diff_ms < timeout);
>  
>   /* Timeout */
>   errno = ETIMEDOUT;
> diff --git a/src/common/utils.c b/src/common/utils.c
> index 3442bef8..c4759f68 100644
> --- a/src/common/utils.c
> +++ b/src/common/ut

[lttng-dev] [PATCH lttng-tools 2/2] Fix: max_t/min_t macros are missing cast on input

2018-11-09 Thread Mathieu Desnoyers
The semantic expected from max_t and min_t is to perform the max/min
comparison in the type provided as first parameter.

Cast the input parameters to the proper type before comparing them,
rather than after. There is no more need to cast the result of the
expression now that both inputs are cast to the right type.

Signed-off-by: Mathieu Desnoyers 
---
 src/common/macros.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/common/macros.h b/src/common/macros.h
index c521aacd..461202ff 100644
--- a/src/common/macros.h
+++ b/src/common/macros.h
@@ -72,7 +72,7 @@ void *zmalloc(size_t len)
 #endif
 
 #ifndef max_t
-#define max_t(type, a, b)  ((type) max(a, b))
+#define max_t(type, a, b)  max((type) a, (type) b)
 #endif
 
 #ifndef min
@@ -80,7 +80,7 @@ void *zmalloc(size_t len)
 #endif
 
 #ifndef min_t
-#define min_t(type, a, b)  ((type) min(a, b))
+#define min_t(type, a, b)  min((type) a, (type) b)
 #endif
 
 #ifndef LTTNG_PACKED
-- 
2.11.0

___
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev


[lttng-dev] [PATCH lttng-tools 1/2] Fix: Connect timeout arithmetic in inet/inet6 (v2)

2018-11-09 Thread Mathieu Desnoyers
The nanoseconds part of the timespec struct time_a is not always
bigger than time_b since it wrap around each seconds.

Use 64-bit arithmetic to perform the difference.

Merge/move duplicated code into utils.c.

This function is really doing two things. Split it into timespec_to_ms()
and timespec_abs_diff().

Signed-off-by: Mathieu Desnoyers 
---
Changes since v1:
- Use NSEC_PER_SEC constant.
---
 src/common/common.h  |  5 +
 src/common/sessiond-comm/inet.c  | 28 
 src/common/sessiond-comm/inet6.c | 28 
 src/common/utils.c   | 31 +++
 4 files changed, 52 insertions(+), 40 deletions(-)

diff --git a/src/common/common.h b/src/common/common.h
index 41eb0361..48f39e0e 100644
--- a/src/common/common.h
+++ b/src/common/common.h
@@ -19,9 +19,14 @@
 #ifndef _COMMON_H
 #define _COMMON_H
 
+#include 
+
 #include "error.h"
 #include "macros.h"
 #include "runas.h"
 #include "readwrite.h"
 
+int timespec_to_ms(struct timespec ts, unsigned long *ms);
+struct timespec timespec_abs_diff(struct timespec ts_a, struct timespec ts_b);
+
 #endif /* _COMMON_H */
diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c
index e0b3e7a9..76a3b7ff 100644
--- a/src/common/sessiond-comm/inet.c
+++ b/src/common/sessiond-comm/inet.c
@@ -112,31 +112,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
sizeof(sock->sockaddr.addr.sin));
 }
 
-/*
- * Return time_a - time_b  in milliseconds.
- */
-static
-unsigned long time_diff_ms(struct timespec *time_a,
-   struct timespec *time_b)
-{
-   time_t sec_diff;
-   long nsec_diff;
-   unsigned long result_ms;
-
-   sec_diff = time_a->tv_sec - time_b->tv_sec;
-   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
-
-   result_ms = sec_diff * MSEC_PER_SEC;
-   result_ms += nsec_diff / NSEC_PER_MSEC;
-   return result_ms;
-}
-
 static
 int connect_with_timeout(struct lttcomm_sock *sock)
 {
unsigned long timeout = lttcomm_get_network_timeout();
int ret, flags, connect_ret;
struct timespec orig_time, cur_time;
+   unsigned long diff_ms;
 
ret = fcntl(sock->fd, F_GETFL, 0);
if (ret == -1) {
@@ -217,7 +199,13 @@ int connect_with_timeout(struct lttcomm_sock *sock)
connect_ret = ret;
goto error;
}
-   } while (time_diff_ms(&cur_time, &orig_time) < timeout);
+   if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time), 
&diff_ms) < 0) {
+   ERR("timespec_to_ms input overflows milliseconds 
output");
+   errno = EOVERFLOW;
+   connect_ret = -1;
+   goto error;
+   }
+   } while (diff_ms < timeout);
 
/* Timeout */
errno = ETIMEDOUT;
diff --git a/src/common/sessiond-comm/inet6.c b/src/common/sessiond-comm/inet6.c
index dfb5fc5d..5c1ac2e0 100644
--- a/src/common/sessiond-comm/inet6.c
+++ b/src/common/sessiond-comm/inet6.c
@@ -110,31 +110,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
sizeof(sock->sockaddr.addr.sin6));
 }
 
-/*
- * Return time_a - time_b  in milliseconds.
- */
-static
-unsigned long time_diff_ms(struct timespec *time_a,
-   struct timespec *time_b)
-{
-   time_t sec_diff;
-   long nsec_diff;
-   unsigned long result_ms;
-
-   sec_diff = time_a->tv_sec - time_b->tv_sec;
-   nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
-
-   result_ms = sec_diff * MSEC_PER_SEC;
-   result_ms += nsec_diff / NSEC_PER_MSEC;
-   return result_ms;
-}
-
 static
 int connect_with_timeout(struct lttcomm_sock *sock)
 {
unsigned long timeout = lttcomm_get_network_timeout();
int ret, flags, connect_ret;
struct timespec orig_time, cur_time;
+   unsigned long diff_ms;
 
ret = fcntl(sock->fd, F_GETFL, 0);
if (ret == -1) {
@@ -216,7 +198,13 @@ int connect_with_timeout(struct lttcomm_sock *sock)
connect_ret = ret;
goto error;
}
-   } while (time_diff_ms(&cur_time, &orig_time) < timeout);
+   if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time), 
&diff_ms) < 0) {
+   ERR("timespec_to_ms input overflows milliseconds 
output");
+   errno = EOVERFLOW;
+   connect_ret = -1;
+   goto error;
+   }
+   } while (diff_ms < timeout);
 
/* Timeout */
errno = ETIMEDOUT;
diff --git a/src/common/utils.c b/src/common/utils.c
index 3442bef8..5b4e1d3c 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -41,6 +42,7 @@
 
 #include "utils.h"
 #include "defaults.h"
+#include "time.h"
 
 /*
  * Return a partial r

Re: [lttng-dev] [PATCH lttng-tools 1/2] Fix: Connect timeout arithmetic in inet/inet6

2018-11-09 Thread Mathieu Desnoyers



- On Nov 9, 2018, at 5:34 PM, Jonathan Rajotte 
jonathan.rajotte-jul...@efficios.com wrote:
[...]
>> +
>> +LTTNG_HIDDEN
>> +struct timespec timespec_abs_diff(struct timespec t1, struct timespec t2)
>> +{
>> +uint64_t ts1 = (uint64_t) t1.tv_sec * INT64_C(10) + (uint64_t)
>> t1.tv_nsec;
>> +uint64_t ts2 = (uint64_t) t2.tv_sec * INT64_C(10) + (uint64_t)
>> t2.tv_nsec;
> 
> Use NSEC_PER_SEC here.
> 
>> +uint64_t diff = max(ts1, ts2) - min(ts1, ts2);
>> +struct timespec res;
>> +
>> +res.tv_sec = diff / INT64_C(10);
> 
> Use NSEC_PER_SEC here.
> 
>> +res.tv_nsec = diff % INT64_C(10);
> 
> Use NSEC_PER_SEC here.

Fixing in v2, thanks,

Mathieu

> 
>> +return res;
>> +}
>> --
>> 2.11.0
>> 
> 
> --
> Jonathan Rajotte-Julien
> EfficiOS

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
___
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev


Re: [lttng-dev] [PATCH lttng-tools 1/2] Fix: Connect timeout arithmetic in inet/inet6 (v2)

2018-11-09 Thread Jonathan Rajotte-Julien
As discussed on IRC, could you make sure to test it manually at least once since
the problematic scenario is never tested by regression test.
Looks much better than my first attempt but we never know.

You can force delay locally using tc.

Something like:

LTTNG_NETWORK_SOCKET_TIMEOUT=4000 lttng-sessiond -b -vvv
lttng-relayd -b
lttng create --live
sudo tc qdisc add dev lo root netem delay 1ms
lttng enable-event -u -a
#Should see errors of connection timeout taking around 4 secs, validate 
using
#the logs.

sudo tc qdisc del dev lo root netem delay 1ms

You can also do the opposite for delays to validate working connect that take a
long time.

As Simon pointed out, unit tests would be even better for these new functions.
Something like test_utils_expand_path.c perhaps? A regression test would be nice
but I'm not sure how we would do it based on the current test framework.

Other comments inline for stuff I did not see the first time.

On Fri, Nov 09, 2018 at 05:40:46PM -0500, Mathieu Desnoyers wrote:
> The nanoseconds part of the timespec struct time_a is not always
> bigger than time_b since it wrap around each seconds.
> 
> Use 64-bit arithmetic to perform the difference.
> 
> Merge/move duplicated code into utils.c.
> 
> This function is really doing two things. Split it into timespec_to_ms()
> and timespec_abs_diff().
> 
> Signed-off-by: Mathieu Desnoyers 
> ---
> Changes since v1:
> - Use NSEC_PER_SEC constant.
> ---
>  src/common/common.h  |  5 +
>  src/common/sessiond-comm/inet.c  | 28 
>  src/common/sessiond-comm/inet6.c | 28 
>  src/common/utils.c   | 31 +++
>  4 files changed, 52 insertions(+), 40 deletions(-)
> 
> diff --git a/src/common/common.h b/src/common/common.h
> index 41eb0361..48f39e0e 100644
> --- a/src/common/common.h
> +++ b/src/common/common.h
> @@ -19,9 +19,14 @@
>  #ifndef _COMMON_H
>  #define _COMMON_H
>  
> +#include 
> +
>  #include "error.h"
>  #include "macros.h"
>  #include "runas.h"
>  #include "readwrite.h"
>  

Given the current format of common.h, wouldn't it be better to have a
timespec_ops.h file with these declaration in it? I guess it can be done in a
later commit to minimize backporting since it is not necessary for the fix.

Please add a comment explaining behaviour on error and what it represent.

> +int timespec_to_ms(struct timespec ts, unsigned long *ms);
> +struct timespec timespec_abs_diff(struct timespec ts_a, struct timespec 
> ts_b);
> +
>  #endif /* _COMMON_H */
> diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c
> index e0b3e7a9..76a3b7ff 100644
> --- a/src/common/sessiond-comm/inet.c
> +++ b/src/common/sessiond-comm/inet.c
> @@ -112,31 +112,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
>   sizeof(sock->sockaddr.addr.sin));
>  }
>  
> -/*
> - * Return time_a - time_b  in milliseconds.
> - */
> -static
> -unsigned long time_diff_ms(struct timespec *time_a,
> - struct timespec *time_b)
> -{
> - time_t sec_diff;
> - long nsec_diff;
> - unsigned long result_ms;
> -
> - sec_diff = time_a->tv_sec - time_b->tv_sec;
> - nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
> -
> - result_ms = sec_diff * MSEC_PER_SEC;
> - result_ms += nsec_diff / NSEC_PER_MSEC;
> - return result_ms;
> -}
> -
>  static
>  int connect_with_timeout(struct lttcomm_sock *sock)
>  {
>   unsigned long timeout = lttcomm_get_network_timeout();
>   int ret, flags, connect_ret;
>   struct timespec orig_time, cur_time;
> + unsigned long diff_ms;
>  
>   ret = fcntl(sock->fd, F_GETFL, 0);
>   if (ret == -1) {
> @@ -217,7 +199,13 @@ int connect_with_timeout(struct lttcomm_sock *sock)
>   connect_ret = ret;
>   goto error;
>   }
> - } while (time_diff_ms(&cur_time, &orig_time) < timeout);
> + if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time), 
> &diff_ms) < 0) {
> + ERR("timespec_to_ms input overflows milliseconds 
> output");
> + errno = EOVERFLOW;
> + connect_ret = -1;
> + goto error;
> + }
> + } while (diff_ms < timeout);
>  
>   /* Timeout */
>   errno = ETIMEDOUT;
> diff --git a/src/common/sessiond-comm/inet6.c 
> b/src/common/sessiond-comm/inet6.c
> index dfb5fc5d..5c1ac2e0 100644
> --- a/src/common/sessiond-comm/inet6.c
> +++ b/src/common/sessiond-comm/inet6.c
> @@ -110,31 +110,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
>   sizeof(sock->sockaddr.addr.sin6));
>  }
>  
> -/*
> - * Return time_a - time_b  in milliseconds.
> - */
> -static
> -unsigned long time_diff_ms(struct timespec *time_a,
> - struct timespec *time_b)
> -{
> - time_t sec_diff;
> - long nsec_diff;
> - unsigned long result_

Re: [lttng-dev] [PATCH lttng-tools 1/2] Fix: Connect timeout arithmetic in inet/inet6 (v2)

2018-11-09 Thread Jonathan Rajotte-Julien


> diff --git a/src/common/utils.c b/src/common/utils.c
> index 3442bef8..5b4e1d3c 100644
> --- a/src/common/utils.c
> +++ b/src/common/utils.c
> @@ -31,6 +31,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -41,6 +42,7 @@
>  
>  #include "utils.h"
>  #include "defaults.h"
> +#include "time.h"
>  
>  /*
>   * Return a partial realpath(3) of the path even if the full path does not
> @@ -1645,3 +1647,32 @@ int utils_show_help(int section, const char *page_name,
>  end:
>   return ret;
>  }
> +
> +LTTNG_HIDDEN
> +int timespec_to_ms(struct timespec ts, unsigned long *ms)
> +{
> + unsigned long res;
> +
> + if (ts.tv_sec + 1 > ULONG_MAX / MSEC_PER_SEC) {
> + return -1;
> + }

This is not accurate. It return -1 for the all the following valid timespec:

   tv_sec = 4294967
   0 < tv_nsec < 29500

You will need to check multiplication and addition separately.

> + res = ts.tv_sec * MSEC_PER_SEC;
> + res += ts.tv_nsec / NSEC_PER_MSEC;
> + *ms = res;
> + return 0;
> +}
> +
> +LTTNG_HIDDEN
> +struct timespec timespec_abs_diff(struct timespec t1, struct timespec t2)
> +{
> + uint64_t ts1 = (uint64_t) t1.tv_sec * (uint64_t) NSEC_PER_SEC +
> + (uint64_t) t1.tv_nsec;
> + uint64_t ts2 = (uint64_t) t2.tv_sec * (uint64_t) NSEC_PER_SEC +
> + (uint64_t) t2.tv_nsec;
> + uint64_t diff = max(ts1, ts2) - min(ts1, ts2);
> + struct timespec res;
> +
> + res.tv_sec = diff / (uint64_t) NSEC_PER_SEC;
> + res.tv_nsec = diff % (uint64_t) NSEC_PER_SEC;
> + return res;
> +}
> -- 
> 2.11.0
> 

-- 
Jonathan Rajotte-Julien
EfficiOS
___
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev