Minutes of the 14th August 2023 Teleconference Austin-1337 Page 1 of 1 Submitted by Andrew Josey, The Open Group. 16th August 2023 Attendees: Don Cragun, IEEE PASC OR Nick Stoughton, Logitech/USENIX, ISO/IEC JTC 1/SC 22 OR Eric Ackermann, HPI, University of Potsdam Geoff Clare, The Open Group Eric Blake, Red Hat, The Open Group OR Mark Ziegast, SHware Systems Dev. (late) Andrew Josey, The Open Group (partial) Apologies Tom Thompson * General news None * Current Business Note for issue resolution all items are tagged for Issue 8 unless noted otherwise or disposition is reject or duplicate. Bug 1627: XSH 3 / mktime() is woefully underspecified Accepted as Marked https://austingroupbugs.net/view.php?id=1627 On page 113 line 3186 section 4.16 Seconds Since the Epoch, change: The relationship between the actual time of day and the current value for seconds since the Epoch is unspecified. to: The relationship between the actual date and time in Coordinated Universal Time, as determined by the International Earth Rotation Service, and the system's current value for seconds since the Epoch is unspecified. On page 1331 line 44320 section mktime(), after applying bugs 1613 and 1614 change: The relationship between the tm structure (defined in the header) and the time in seconds since the Epoch is that the result shall be as specified in the expression given in the definition of seconds since the Epoch (see [xref to XBD 4.19]) corrected for the offset of the timezone's standard time from Coordinated Universal Time and further corrected (if applicable--see below) for Daylight Saving Time, where the names other than tm_yday in the structure and in the expression correspond, and the tm_yday value used in the expression is the day of the year from 0 to 365 inclusive, calculated from the members of the tm structure specified above. to: The mktime() function shall calculate the time in seconds since the Epoch to be returned as if by manipulating the members of the tm structure according to the following steps. 1. The tm_sec member may, but should not, be brought into the range 0 to 60, inclusive. For each 60 seconds added to or subtracted from tm_sec, a decrement or increment, respectively, of 1 minute shall be saved for later application. 2. The tm_min member shall be brought into the range 0 to 59, inclusive, and any saved decrement or increment of minutes shall then be applied, repeating the range adjustment afterwards if necessary. For each 60 minutes added to or subtracted from tm_min, a decrement or increment, respectively, of 1 hour shall be saved for later application. 3. The tm_hour member shall be brought into the range 0 to 23, inclusive, and any saved decrement or increment of hours shall then be applied, repeating the range adjustment afterwards if necessary. For each 24 hours added to or subtracted from tm_hour, a decrement or increment, respectively, of 1 day shall be saved for later application. 4. The tm_mon member shall be brought into the range 0 to 11, inclusive. For each 12 months added to or subtracted from tm_mon, a decrement or increment, respectively, of 1 year shall be saved for later use. 5. The tm_mday member shall be brought into the range 1 to 31, inclusive, and any saved decrement or increment of days shall then be applied, repeating the range adjustment afterwards if necessary. Adjustments downwards shall be applied by subtracting the number of days (according to the Gregorian calendar) in month tm_mon+1 of the year obtained by adding/subtracting any saved increment/decrement of years to the value tm_year+1900, and then incrementing tm_mon by 1, repeated as necessary. Adjustments upwards shall be applied by adding the number of days in the month before month tm_mon+1 of the year obtained by adding/subtracting any saved increment/decrement of years to the value tm_year+1900, and then decrementing tm_mon by 1, repeated as necessary. During these adjustments, the tm_mon value shall be kept within the range 0 to 11, inclusive, by applying step 4 as necessary. 6. If the tm_mday member is greater than the number of days in month tm_mon+1 of the year obtained by adding/subtracting any saved increment/decrement of years to the value tm_year+1900, that number of days shall be subtracted from tm_mday, and tm_mon shall be incremented by 1. If this results in tm_mon having the value 12, step 4 shall be applied. 7. The number of seconds since the Epoch in Coordinated Universal Time shall be calculated from the range-corrected values of the relevant tm structure members (or the original value where a member was not range corrected) as specified in the expression given in the definition of seconds since the Epoch (see [xref to XBD 4.19]), where the names other than tm_year and tm_yday in the structure and in the expression correspond, the tm_year value used in the expression is the tm_year in the structure plus/minus any saved increment/decrement of years, and the tm_yday value used in the expression is the day of the year from 0 to 365 inclusive, calculated from the tm_mon and tm_mday members of the tm structure, for that year. 8. The time since the Epoch shall be corrected for the offset of the local timezone's standard time from Coordinated Universal Time. 9. The time since the Epoch shall be further corrected (if applicable--see below) for Daylight Saving Time. On page 1332 line 44357 section mktime(), change APPLICATION USAGE from "None" to: When using mktime() to add or subtract a fixed time period (one that always corresponds to a fixed number of seconds) to or from a broken-down time in the local timezone, reliable results for arbitrary TZ can only be assured by using mktime() to convert the original broken-down time to a time since the Epoch, adding or subtracting the desired number of seconds to that value, and then calling localtime() with the result. The alternative of adjusting the broken-down time before calling mktime() may produce unexpected results if the original and updated times are on different sides of a geographical timezone change. On implementations that follow the recommendation of not range-correcting tm_sec (see step 1 in the DESCRIPTION), reliable results can also be assured by adding or subtracting the desired number of seconds to tm_sec (and not modifying any other members of the tm structure). In applications needing to be portable to non-POSIX systems where the time_t encoding is not a count of seconds, it is recommended that conditional compilation is used such that the adjustment is performed on the mktime() return value when possible, and otherwise on the tm_sec member. For timezones that are known not to have geographical timezone changes, such as TZ=UTC0, adjustments using just mktime() do not have this problem. The way the mktime() function interprets out-of-range tm structure fields might not produce the expected result when multiple adjustments are made at the same time. For example, if an application tries to go back one day first and then one year by calling localtime(), decrementing tm_mday and tm_year, and then calling mktime() this would not produce the expected result if it was called on 2021-03-01 because mktime() would see the supplied year as 2020 (a leap year) and correct Mar 0 to Feb 29, whereas the intended result was Feb 28. Such issues can be avoided by doing multiple adjustments one at a time when the order in which they are done matters. Examples of how mktime() handles some adjustments are: If given Feb 29 in a non-leap year it treats that as the day after Feb 28 and gives back Mar 1. If given Feb 0 it treats that as the day before Feb 1 and gives back Jan 31. If given 21:65 it treats that as 6 minutes after 21:59 and gives back 22:05. If given tm_isdst=0 for a time when DST is in effect, it gives back a positive tm_isdst and alters the other fields appropriately. If there is a DST transition where 02:00 standard time becomes 03:00 DST and mktime() is given 02:30 (with negative tm_isdst), it treats that as either 30 minutes after 02:00 standard time or 30 minutes before 03:00 DST and gives back a zero or positive tm_isdst, respectively, with the tm_hour field altered appropriately. If a geographical timezone changes its UTC offset such that ``old 00:00'' becomes ``new 00:30'' and mktime() is given 00:20, it treats that as either 20 minutes after ``old 00:00'' or 10 minutes before ``new 00:30'', and gives back appropriately altered struct tm fields. If an application wants to check whether a given broken-down time is one that is skipped over, it can do so by seeing whether the tm_mday, tm_hour, and tm_min values it gets back from mktime() are the same ones it fed in. Just checking tm_hour and tm_min might appear at first sight to suffice, but tm_mday could also change--without tm_hour and tm_min changing--if, for example, TZ is set to "ABC12XYZ-12" (which might be used in a torture test) or if a geographical timezone changes the offset from Coordinated Universal Time of its standard time by 24 hours. On page 1332 line 44359 section mktime(), change RATIONALE from "None" to: Implementations are encouraged not to range-correct tm_sec (see step 1 in the DESCRIPTION) in order for the results of making an adjustment to tm_sec always to be equivalent to making the same adjustment to the value returned by mktime(), even when the original and updated times are on different sides of a geographical timezone change. This provides a way for applications to do reliable fixed-period adjustment using only mktime(), as described in APPLICATION USAGE. The described method for range-correcting the tm structure members uses separate variables to hold adjustment values to be applied later to other members, or (for the year adjustment) used in later calculations, because this is one way of avoiding intermediate member values that are not representable as an int. Implementations may use other methods; all that is required is that tm_year is the only member for which an [EOVERFLOW] error can occur. The described method for range-correcting tm_mday would, if implemented that way, be highly inefficient for very large values. The efficiency can be improved by observing that any period of 400 years always has the same number of days, so the month-by-month correction method need only be applied for a maximum of 4800 months. On page 1332 line 44361 section mktime(), change FUTURE DIRECTIONS from "None" to: A future version of this standard may require that mktime() does not perform the optional range correction of the tm_sec member of the tm structure described at step 1 in the DESCRIPTION. A future version of this standard is expected to add a timegm() function that is similar to mktime(), except that the tm structure pointed to by timeptr contains a broken-down time in Coordinated Universal Time (rather than the local timezone), where references to localtime() are replaced by references to gmtime(), and where there are no timezone offset or Daylight Saving Time adjustments. A combination of gmtime() and timegm() will be the expected way to perform arithmetic upon a time_t value and remain compatible with the ISO C standard (where the internal structure of a time_t is not specified), since attempting such manipulations using localtime() and mktime() can lead to unexpected results. Bug 728: Restrictions on signal handlers are both excessive and insufficient Accepted as Marked https://austingroupbugs.net/view.php?id=728 See note 6138 regarding the C23 ballot resolution. On Issue 8 draft 3 page 516 line 18330 section 2.4.3, change: the behavior is undefined if the signal handler refers to any object other than errno with static or thread storage duration that is not a lock-free atomic object, other than by assigning a value to an object declared as volatile sig_atomic_t, or if the signal handler calls any function or function-like macro defined in this standard other than one of the functions and macros specified below as being async-signal-safe. to: the behavior is undefined if: The signal handler refers to any object other than errno with static or thread storage duration that is not a lock-free atomic object, and not a non-modifiable object (for example, string literals, objects that were defined with a const-qualified type, and objects in memory that is mapped read-only), other than by assigning a value to an object declared as volatile sig_atomic_t, unless the previous modification (if any) to the object happens before the signal handler is called and the return from the signal handler happens before the next modification (if any) to the object. The signal handler calls any function or function-like macro defined in this standard other than one of the functions and macros specified below as being async-signal-safe. On Issue 8 draft 3 page 2049 line 67324 section signal(), change: the behavior is undefined if the signal handler refers to any object [CX]other than errno[/CX] with static or thread storage duration that is not a lock-free atomic object, other than by assigning a value to an object declared as volatile sig_atomic_t, or if the signal handler calls any function defined in this standard other than [CX]one of the functions listed in Section 2.4 (on page 511)[/CX]. to: the behavior is undefined if: The signal handler refers to any object [CX]other than errno[/CX] with static or thread storage duration that is not a lock-free atomic object, [CX]and not a non-modifiable object (for example, string literals, objects that were defined with a const-qualified type, and objects in memory that is mapped read-only)[/CX], other than by assigning a value to an object declared as volatile sig_atomic_t, [CX]unless the previous modification (if any) to the object happens before the signal handler is called and the return from the signal handler happens before the next modification (if any) to the object[/CX]. The signal handler calls any function defined in this standard other than [CX]one of the functions listed in Section 2.4 (on page 511)[/CX]. Bug 708: Make mblen, mbtowc, and wctomb thread-safe for alignment with C11 Accepted as Marked https://austingroupbugs.net/view.php?id=708 In all of these changes the placeholder XXXX should be replaced with the name of the function. Page and line numbers are for Issue 8 draft 2.1. On page 1274 line 42635 section mblen(), and page 1285 line 42996 section mbtowc(), and page 2255 line 72488 section wctomb(), change: The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-202x defers to the ISO C standard. to: Except for requirements relating to data races, the functionality described on this reference page is aligned with the ISO C standard. Any other conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-202x defers to the ISO C standard for all XXXX() functionality except in relation to data races. On page 1274 line 42652 section mblen(), and page 1285 line 43015 section mbtowc(), and page 2255 line 72505 section wctomb(), change: [CX]The XXXX() function need not be thread-safe.[/CX] to: The XXXX() function [CX]need not be thread-safe; however, it[/CX] shall avoid data races with all other functions. On page 1274 line 42669 section mblen(), and page 1286 line 43032 section mbtowc(), and page 2255 line 72522 section wctomb(), change RATIONALE from "None" to: When the ISO C standard introduced threads in C11, it required XXXX() to avoid data races (with itself as well as with other functions), whereas POSIX.1-2008 did not require it to be thread-safe, and in many implementations it did not avoid data races with itself and still does not. The ISO C committee intend to change the requirements in a future version of the ISO C standard, but since POSIX.1 currently refers to C17 it is necessary for it not to defer to the ISO C standard regarding data races in order to continue to allow this function not to avoid data races with itself. On page 1274 line 42669 section mblen(), and page 1286 line 43034 section mbtowc(), and page 2256 line 72524 section wctomb(), change FUTURE DIRECTIONS from "None" to: It is expected that a change in a future version of the ISO C standard will allow a future version of this standard to remove the data race exception from the statement that it defers to the ISO C standard. Next Steps ---------- The next call is on: Thu 2023-08-17 (Zoom meeting - general bugs/ballot resolution) Mon 2023-08-21 (Zoom meeting - general bugs/ballot resolution) The calls are for 90 minutes Calls are anchored on US time. (8am Pacific) Please check the calendar invites for dial in details. Bugs are at: https://austingroupbugs.net An etherpad is usually up for the meeting, with a URL using the date format as below: https://posix.rhansen.org/p/20xx-mm-dd (For write access this uses The Open Group single sign on, for those individuals with gitlab.opengroup.org accounts. Please contact Andrew if you need to be setup)