[m-rev.] for review: improve error checking in the time module

Julien Fischer jfischer at opturion.com
Mon Aug 9 02:35:07 AEST 2021


Hi Zoltan,

On Mon, 9 Aug 2021, Zoltan Somogyi wrote:

> On Sun, 8 Aug 2021 23:25:58 +1000 (AEST), Julien Fischer <jfischer at opturion.com> wrote:
>> @@ -205,7 +206,10 @@
>>           #include <unistd.h>
>>       #endif
>>
>> -    #include ""mercury_timing.h"" // for MR_CLOCK_TICKS_PER_SECOND
>> +    #include ""mercury_timing.h""       // for MR_CLOCK_TICKS_PER_SECOND
>> +    #include ""mercury_runtime_util.h"" // For MR_sterror.
>
> MR_stRerror

Fixed.

>>   localtime(Time, TM, !IO) :-
>>       Time = time_t(RawTime),
>> -    c_localtime(RawTime, Yr, Mnt, MD, Hrs, Min, Sec, YD, WD, N, !IO),
>> -    TM = tm(Yr, Mnt, MD, Hrs, Min, Sec, YD, WD, int_to_maybe_dst(N)).
>> +    c_localtime(RawTime, IsOk, Yr, Mnt, MD, Hrs, Min, Sec, YD, WD, N,
>> +        ErrorMsg, !IO),
>
> You may want to rename c_X to something like target_X, since it is
> a bit surprising to have a non-C foreign proc for something whose name
> implies it is specifically for C.

Done.

>> @@ -647,27 +704,37 @@ gmtime(time_t(Time)) = TM :-
>>       t = Time;
>>
>>       p = gmtime(&t);
>> -
>> -    // XXX do we need to handle the case where p == NULL here?
>> -
>> -    Sec = (MR_Integer) p->tm_sec;
>> -    Min = (MR_Integer) p->tm_min;
>> -    Hrs = (MR_Integer) p->tm_hour;
>> -    Mnt = (MR_Integer) p->tm_mon;
>> -    Yr = (MR_Integer) p->tm_year;
>> -    WD = (MR_Integer) p->tm_wday;
>> -    MD = (MR_Integer) p->tm_mday;
>> -    YD = (MR_Integer) p->tm_yday;
>> -    N = (MR_Integer) p->tm_isdst;
>> +    if (p == NULL) {
>> +        char errbuf[MR_STRERROR_BUF_SIZE];
>> +        const char *errno_msg;
>> +        IsOk = MR_NO;
>> +        errno_msg = MR_strerror(errno, errbuf, sizeof(errbuf));
>> +        MR_save_transient_hp();
>> +        MR_make_aligned_string_copy(ErrorMsg, errno_msg);
>> +        MR_restore_transient_hp();
>> +    } else {
>> +        IsOk = MR_YES;
>> +        Sec = (MR_Integer) p->tm_sec;
>> +        Min = (MR_Integer) p->tm_min;
>> +        Hrs = (MR_Integer) p->tm_hour;
>> +        Mnt = (MR_Integer) p->tm_mon;
>> +        Yr = (MR_Integer) p->tm_year;
>> +        WD = (MR_Integer) p->tm_wday;
>> +        MD = (MR_Integer) p->tm_mday;
>> +        YD = (MR_Integer) p->tm_yday;
>> +        N = (MR_Integer) p->tm_isdst;
>> +        ErrorMsg = MR_make_string_const(\"\");
>> +    }
>
> You should be consistent about whether you fill in
> the "success" output args if IsOk = no. Either do it
> in all the foreign procs that return IsOk, or none of them.
> Likewise, set ErrorMsg to "" either in all the IsOk = yes cases,
> or none of them.

Done.

>> -    if (N == 1 & !isDST) {
>> -        // If the time we constructed is not in daylight savings time, but it
>> -        // should be, we need to subtract the DSTSavings.
>> -        java.time.Duration savings = rules.getDaylightSavings(Time0);
>> -        Time = Time0.minus(savings);
>> -        if (!rules.isDaylightSavings(Time)) {
>> -            throw new RuntimeException(
>> -                ""time.mktime: failed to correct for DST"");
>> +    try {
>> +        java.time.ZoneId tz = java.time.ZoneId.systemDefault();
>> +        java.time.Instant Time0 = java.time.ZonedDateTime.of(
>> +            java.time.LocalDateTime.of(Yr + 1900, Mnt + 1, MD, Hrs, Min, Sec),
>> +            tz).toInstant();
>
> Seeing "tz)" at the *start* of a line is jarring.

Do you have an alternative formatting in mind (that doesn't exceed the
80 char line limit)?  Or is your comment related to the use of "tz" as a
local variable name, as opposed to say "time_zone"?

> I am not familiar with the non-C primitives some of this code
> is calling, but as far as I can tell, the rest is fine.

The underlying primitives we call have not changed; we just check
what they're returning more strongly.

Julien.


More information about the reviews mailing list