Anonymous | Login | 2024-12-12 14:23 UTC |
Main | My View | View Issues | Change Log | Docs |
Viewing Issue Simple Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||
ID | Category | Severity | Type | Date Submitted | Last Update | ||
0001151 | [1003.1(2016/18)/Issue7+TC2] System Interfaces | Editorial | Enhancement Request | 2017-06-19 16:41 | 2024-06-11 09:09 | ||
Reporter | Clausecker | View Status | public | ||||
Assigned To | |||||||
Priority | normal | Resolution | Accepted As Marked | ||||
Status | Closed | ||||||
Name | Robert Clausecker | ||||||
Organization | Fraunhofer Fokus | ||||||
User Reference | |||||||
Section | termios.h, signal.h, 2.4.3 "Signal Actions", 11.2 "Parameters that Can be Set", new sections tcgetsize and tcsetsize | ||||||
Page Number | 414, 333, 494, 212 | ||||||
Line Number | 13877, 11115, 16845–16879, 7040 | ||||||
Interp Status | --- | ||||||
Final Accepted Text | See Note: 0003856 | ||||||
Summary | 0001151: Introduce new signal SIGWINCH and functions tcsetsize(), tcgetsize() to get/set terminal window size | ||||||
Description |
This proposal aims to standardize the broadly available signal SIGWINCH and an extension to termios to query and set the terminal window size. This extension is designed to be easily implementable in terms of the TIOCGWINSZ and TIOCSWINSZ ioctl() calls available on many UNIX-like systems. This proposal does not contain an extension to the stty utility as that is already considered in the scope of [bug 1053]. This proposal introduces new functions tcgetsize() and tcsetsize() instead of introducing the ioctl() calls TIOCGWINSZ and TIOCSWINSZ as POSIX generally does not standardize the ioctl() except for the STREAMS interface. The desired action is rather large and posted both inline and as an attachment to the bug report in case the bug tracker garbles it. [bug 1053]: http://austingroupbugs.net/view.php?id=1053 [^] |
||||||
Desired Action |
Extensions to termios.h ======================= A new subsection named "The winsize structure" is added to the header termios.h right after the section "The termios structure." The type "unsigned short" follows historical convention. Perhaps the comittee wishes to instead introduce appropriate integer types for the structure members instead. This might be useful for implementations aiming to support terminals with more than 65535 horizontal or vertical pixels. The winsize Structure --------------------- The <termios.h> header shall define the winsize structure, which shall include at least the following members: unsigned short ws_row rows, in characters. unsigned short ws_col columns, in characters. unsigned short ws_xpixel horizontal size, in pixels. unsigned short ws_ypixel vertical size, in pixels. In all members named in this volume of POSIX.1 2008, a value of 0 shall indicate that the value is unknown. Furthermore, the list of declared functions shall be amended with the following two entries: int tcgetsize(int, struct winsize *); int tcsetsize(int, const struct winsize *); The section "CHANGE HISTORY" shall be amended appropriately. Extensions to signal.h ====================== The table of signals shall be amended with the following entry: Signal: SIGWINCH Default Action: I Description: Window size changed. The entry shall be added immediately after the entry for SIGUSR1. The section "CHANGE HISTORY" shall be amended appropriately. Extensions to §2.4.3 Signal Actions =================================== The list of async-signal-safe functions shall be amended by the functions tcgetsize() and tcsetsize(). New function "tcgetsize" ======================== A new page "tcgetsize" shall be added to the list of system interfaces. Its text is analogous to that of tcgetattr and shall be as follows: NAME tcgetsize -- get the window size associated with a terminal SYNOPSIS #include <termio.h> int tcgetsize(int fildes, struct winsize *winsize_p); DESCRIPTION The tcgetsize() function shall get the window size associated with the terminal referred to by fildes and store them in the winsize structure pointed to by winsize_p. The fildes argument is an open file descriptor associated with a terminal. The winsize_p argument is a pointer to a winsize structure. It is implementation defined whether the window size associated with a terminal refers to the actual size and resolution of the terminal connected to the communication port associated with the terminal. The tcgetsize() operation is allowed from any process. RETURN VALUE Upon succesful completion, 0 shall be returned. Otherwise, -1 shall be returned and errno set to indicate the error. ERRORS The tcgetsize() function shall fail if: [EBADF] The fildes argument is not a valid file descriptor. [ENOTTY] The file associated with fildes is not a terminal. EXAMPLES The following example demonstrates how tcgetsize can be used in conjunction with a handler for SIGWINCH to keep track of the terminal window size associated with the standard error stream. #include <stdio.h> #include <signal.h> #include <termios.h> #include <unistd.h> static struct winsize ws; static void winch_handler(int signum) { (void)signum; if (tcgetsize(STDERR_FILENO, &ws) == -1) /* Handle error. */ } int main() { struct sigaction sa; sa.sa_handler = winch_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGWINCH, &sa, NULL); for (winch_handler(SIGWINCH); ; pause()) printf("row = %3d, col = %3d, xpixel = %4d, ypixel = %4d\n", ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel); } APPLICATION USAGE None. RATIONALE The tcgetsize() function is provided to allow applications to query the current size of a terminal window. This is necessary for applications intended to be run in terminal emulators whose window size can be changed at runtime. A SIGWINCH signal is delivered to a terminal's process group whenever its window size is changed. By installing a signal handler for SIGWINCH, a process can detect the resizing of its controlling terminal and take action, e.g. by redrawing its user interface to the new size. FUTURE DIRECTIONS None. SEE ALSO tcsetsize, <termios.h> The "CHANGE HISTORY" section shall be filled in appropriately. New function "tcsetsize" ======================== A new page "tcsetsize" shall be added to the list of system interfaces. Its text is analogous to that of tcsetattr and shall be as follows: NAME tcsetsize -- set the window size associated with a terminal SYNOPSIS #include <termios.h> int tcsetsize(int fildes, const struct winsize *winsize_p); DESCRIPTION The tcsetsize() function shall set the window size associated with the terminal referred to by the open file descriptor fildes (an open file descriptor associated with a terminal) from the winsize structure referenced by winsize_p. The change shall occur immediately. If the terminal size was changed succesfully, a SIGWINCH shall be delivered to the foreground process group associated with the terminal. If the terminal is a slave pseudo-terminal, a SIGWINCH shall also be delivered to the foreground process group of the associated master pseudo-terminal. Similarly, if the terminal is a master pseudo-terminal, a SIGWINCH shall be delivered to the foreground process group of the associated slave pseudo-terminal. No signal shall be delivered if the terminal size and resolution were changed to the same value they had before the tcsetsize() call. If the foreground process groups of master and slave pseudo-terminals are the same, only one SIGWINCH shall be delivered to the process group. If one of the mentioned foreground process groups does not exist, the corresponding signal shall not be delivered. The tcsetsize() function shall return successfully if it was able to alter the terminal size or resolution. It is implementation defined whether changing the window size of a terminal causes any changes in the size or resolution of the terminal emulator's graphical output. The effect of tcsetsize() is undefined if the value of the winsize structure pointed to by winsize_p was not derived from the result of a call to tcgetsize() on fildes; an application should only modify only fields defined by this volume of POSIX.1-2008 between the call to tcgetsize() and tcsetsize(), leaving all other fields unmodified. No actions defined by this volume of POSIX.1-2008, other than a call to tcsetsize(), a close of the last file descriptor in the system associated with this terminal device, or an open of the first file descriptor in the system associated with this terminal device (using the O_TTY_INIT flag if it is non-zero and the device is not a pseudo-terminal), shall cause any of the terminal attributes defined by this volume of POSIX.1-2008 to change. RETURN VALUE Upon successful completion, 0 shall be returned. Otherwise, -1 shall be returned and errno set to indicate the error. ERRORS The tcsetsize() shall fail if: [EBADF] The fildes argument is not a valid file descriptor. [EINVAL] An attempt was made to change an attribute represented in the winsize structure to an unsupported value. [ENOTTY] The file associated with fildes is not a terminal. EXAMPLES None. APPLICATION USAGE If the window of a graphical terminal emulator is resized, the terminal emulator should invoke tcsetsize() to relay the new window size and resolution to the slave's foreground process group. If a process attached to the slave of a graphical terminal emulator's pseudo-terminal calls tcsetsize(), the terminal emulator should attempt to change the window size and resolution to reflect the requested terminal size. RATIONALE None. FUTURE DIRECTIONS None. SEE ALSO tcgetsize, <termios.h> The "CHANGE HISTORY" section shall be filled in appropriately. New section §11.2.7 Window Size =============================== Immediately after §11.2.6 "Special Control Characters," a new section named "Window Size" shall be added with the following text: 11.2.7 Window Size Routines that need to query or set the terminal window size shall do so by using the winsize structure as defined in the <termios.h> header. Since the winsize structure may include additional members, the structure should never be initialized directly by the application as this may cause the terminal to behave in a non-conforming manner. When opening a terminal device (other than a pseudo-terminal) that is not already open in any process, it should be opened with the O_TTY_INIT flag before initializing the structure using tcgetsize() to ensure that any non-standard elements of the termios structure are set to values that result in conforming behavior of the terminal interface. The members of the winsize structure include (but are not limited to): +----------------+-------------+----------------------------+ | Member Type | Member Name | Description | +----------------+-------------+----------------------------+ | unsigned short | ws_row | rows, in characters | | unsigned short | ws_col | columns, in characters | | unsigned short | ws_xpixel | horizontal size, in pixels | | unsigned short | ws_ypixel | vertical size, in pixels | +----------------+-------------+----------------------------+ For each member, a value of 0 indicates that the size is unknown. A program can query the window size associated with a terminal using the tcgetsize() function and alter the window size using the tcsetsize() function. Updating the window size causes a SIGWINCH to be delivered to the terminal's foreground process group if any. It is implementation-defined whether the window size associated with a terminal actually corresponds to the physical size and resolution of the physical or virtual terminal device connected to the terminal's communication port. If it does correspond, changing the size or resolution of the terminal device causes a SIGWINCH to be sent to the foreground process group of the terminal. |
||||||
Tags | issue8 | ||||||
Attached Files |
sigwinch-proposal.txt [^] (12,847 bytes) 2017-06-19 16:41 sigwinch_example.c [^] (2,133 bytes) 2017-06-29 09:12 sigwinch-proposal.2.txt [^] (9,590 bytes) 2017-08-31 09:19 sigwinch_example.2.c [^] (1,750 bytes) 2017-09-14 07:41 |
||||||
|
Relationships | |||||||||||||
|
Notes | |
(0003786) shware_systems (reporter) 2017-06-19 17:32 edited on: 2017-08-17 15:24 |
Extensions to termios.h ======================= A new subsection named "The winsize_t structure" is added to the header termios.h right after the section "The termios structure." The type "unsigned short" follows historical convention. Perhaps the committee wishes to instead introduce appropriate integer types for the structure members instead. This might be useful for implementations aiming to support terminals with more than 65535 horizontal or vertical pixels. The winsize_t Structure --------------------- The <termios.h> header shall define the winsize_t structure, which shall include at least the following members: unsigned long ws_row rows, in characters. unsigned long ws_col columns, in characters. [XSI] or [UP] unsigned long ws_xpixel horizontal size, in pixels, if supported. unsigned long ws_ypixel vertical size, in pixels, if supported. [x] In all members named in this volume of POSIX.1 2008, a value of 0 shall indicate that the value is unknown. === Additional edits after as winsize an app reserved identifier, *_t standard / implementation reserved. Use of termios as a type identifier a grandfathered allowance. Changed to long as display arrays can have now over 65k chars or pixels easily enough with UHD 4k resolutions, yet be logically a single terminal. The future is already here, iow. :-) Option group added as base POSIX will still only require support for char array or line oriented devices, not pixel or vector based. This was part of Bug 1053 discussion. Moving any added support for vectors or pixels to the base is an Issue 9 matter. Errors for tcsetsize() is missing ENOSUP as a 'may fail' entry, also discussed, for terminals that have fixed dimensions. Believe additional text related to LINES and COLUMNS env. variables also desirable. |
(0003787) EdSchouten (reporter) 2017-06-19 18:06 |
Why call it winsize_t, as opposed to 'struct winsize', which is the current convention? |
(0003788) shware_systems (reporter) 2017-06-19 18:11 |
Because other applications may use winsize for other purposes, as struct tag or other context. |
(0003789) Clausecker (reporter) 2017-06-19 18:43 |
struct winsize is the historic name for this structure, used since at least 1989. Renaming it might cause more problems than it solves. Note that tcsetsize and tcgetsize aren't reserved by POSIX either (probably by mistake). Mandating unsigned long as the type for the members is a bad idea as this contradicts existing implementations. All implementations I checked use unsigned short for this type. As I already mentioned, introducing a typedef windim_t might be a good compromise between compatibility and future expansions. I don't see how adding ENOTSUP might be a good idea. If the terminal's size cannot be changed, an implementation may either decide to make size changes have no effect (this might be a good idea for serial ports where the device driver cannot change the terminal but e.g. login(8) might want to set up the window size with information from the termcap database) or decide that each other possible terminal size is invalid, returning EINVAL. Changing the terminal size to itself should never cause an error, even on a fixed-size terminal. Perhaps that invariant should be specified, too. |
(0003791) geoffclare (manager) 2017-06-20 09:22 |
There are some signal-related problems with the example code. 1. The winch_handler() function needs to save errno on entry and restore it before returning. 2. Having the tcgetsize() call in winch_handler() write directly to the static structure is undefined behaviour. To meet the requirements of the current standard it would have to write to a local structure and then copy each member to a separate static value of type volatile sig_atomic_t. However, since (if accepted) this will go into Issue 8 it may be better to use the new C11 lock-free atomic objects. 3. In main() if a second SIGWINCH arrives during execution of the loop, printf() could end up printing some old and some new values. The code should block SIGWINCH before the loop, and should use sigsuspend() instead of pause(). In addition to correcting the example code, there should be some discussion of points 2 and 3 in the APPLICATION USAGE section, plus a mention that multi-threaded processes should use sigwait() instead of a signal handler. |
(0003797) shware_systems (reporter) 2017-06-22 10:36 |
Renaming it is required by XSH 2.2.2 Namespaces, afaik, whatever problems ensue. Last it was discussed new identifiers to be standardized were being drawn from the namespace reserved to implementations by the C standard since C89 or with prefixes / suffixes reserved by POSIX and C to implementations, for additions to any of the standard libraries. That those platforms used a file-scope-visible identifier reserved to applications with winsize is therefore their lookout, not the standard's, and this is not an exception from before Issue 1 or C89 that I see. Whether the interfaces should be posix_get/setsize() or posix_tcget/setsize() is open to debate, perhaps. As proposed what's there is usable if controlled by a visibility macro, to maintain backwards compatibility, but I forgot to add that part to the note. As apparently no platform is using winsize_t, using longs has no known backwards compatibility considerations for this functionality. Imo bug reports should have been filed over a decade ago with those platforms to obsolete the interfaces where the structure members are shorts, as being short sighted, for collateral issues. I agree use of an opaque type is plausible, but this has the overhead of adding min and max constant specifications too and still obsoletes that structure. ENOTSUP being returned is a case where the signal would not be generated because no attempt to access the device is being performed. This would be different from a device accepting a set command that has only one valid value, but may have side effects such as doing a form feed or clear screen, so the signal should be generated. This would return EINVAL if another value was passed in, I'd expect. |
(0003798) geoffclare (manager) 2017-06-22 16:45 |
I see a problem with this part of the tcsetsize() description:If the terminal is a slave pseudo-terminal, a SIGWINCH shall also be delivered to the foreground process group of the associated master pseudo-terminal. Similarly, if the terminal is a master pseudo-terminal, a SIGWINCH shall be delivered to the foreground process group of the associated slave pseudo-terminal. Currently the standard does not require the master side to provide a terminal interface nor require that it can have a controlling process or process groups. All it requires of the master is (XBD 3.308) "Anything written on the master device is presented to the slave as an input and anything written on the slave device is presented as an input on the master side." How best to solve this depends on whether existing applications expect the master side to be a terminal and for what reason (e.g. is it always just in order to receive SIGWINCH when the slave side changes size). |
(0003799) Don Cragun (manager) 2017-06-22 16:52 |
From the text in this proposal, I don't understand whether a user or application using these interfaces is expected to change the value assigned to ws_xpixel at the same time the value of ws_row is changed (and vice versa) and to change the value assigned to ws_ypixel at the same time the value of ws_col is changed (and vice versa); whether a user or application is only expected to use one pair of these values and never look at or change the other set (and, if so, how to know which pair of values to use to achieve whatever different affects are to be expected from using the two pairs of values); nor whether or not there is any relationship between the ws_row and ws_col values and the ws_[xy]pixel values. If a user calls tcgetsize() and modifies ws_col and ws_row without changing ws_[xy]pixel before calling tcsetsize() to alter those values, is the system expected to modify the pixel values as a side effect of the call? Should it return an error in this case since the pixel values no longer correlate to the row and col values? Should an application always set the pixel values to 0 if the row/col values are changed and set the row/col values to 0 if the pixel values are changed? Would the submitter of this bug please add a note with additional text indicating the relationships between these pairs of values, an explanation of what each pair of values is intended to do, and advice for readers of the standard so they know which values to use and which values to modify for the intended use cases of each pair of values? |
(0003800) Clausecker (reporter) 2017-06-22 20:53 |
> There are some signal-related problems with the example code. It perhaps might be a good idea to omit the example then as I don't see how to make the example be strictly correct without being overly complicated at the same time. > Currently the standard does not require the master side to provide a terminal interface nor require that it can have a controlling process or process groups. All it requires of the master is (XBD 3.308) "Anything written on the master device is presented to the slave as an input and anything written on the slave device is presented as an input on the master side." Reading various kernel source again, this seems to be an exclusive Linux feature. Perhaps this paragraph should be removed or replaced with a paragraph allowing SIGWINCH to be delivered to an implementation defined set of additional processes. > Would the submitter of this bug please add a note with additional text indicating the relationships between these pairs of values, an explanation of what each pair of values is intended to do, and advice for readers of the standard so they know which values to use and which values to modify for the intended use cases of each pair of values? This seems to differ between implementation. The general use case for tcsetsize() seems to be for terminal emulators or the kernel's virtual console to set the current terminal size. If I understood the Linux source code correctly, the kernel ignores ws_xpixel and ws_ypixel and treats zeroes as “no change”. Then it tries to find a video mode that has the desired number of rows and columns and changes to that. In Solaris, I have not found any place where a call to tcsetsize() causes a video mode change, though some comments in common/io/ptem.c seem to suggest that it once did. On FreeBSD I have not found such code either, though, changing the video mode does change the terminal window size as reported by ioctl(TIOCGWINSZ, ...); and a SIGWINCH is delivered. > If a user calls tcgetsize() and modifies ws_col and ws_row without changing ws_[xy]pixel before calling tcsetsize() to alter those values, is the system expected to modify the pixel values as a side effect of the call? Should it return an error in this case since the pixel values no longer correlate to the row and col values? Should an application always set the pixel values to 0 if the row/col values are changed and set the row/col values to 0 if the pixel values are changed? Note that on real hardware, rows/columns do not determine resolution. It is possible that the console driver supports more than one video mode for the same number of rows and columns, e.g. two modes with different aspect ratios. However, I do not know any implementation that considers ws_[xy]pixel when setting the terminal window size. I wrote that it is implementation defined if tcsetsize() actually changes the terminals resolution (as opposed to merely adjusting the value returned by tcgetsize()) because the behaviour differs among operating systems. |
(0003804) geoffclare (manager) 2017-06-29 09:20 |
I have created an updated example program with the points from Note: 0003791 fixed, and attached it as sigwinch_example.c The code above the "cut here" line is for testing purposes, and wouldn't be included in the standard. It uses sig_atomic_t because that is what's in the current standard and also because C11 lock-free atomic objects are optional in C11, so will likely be optional in Issue 8. We could include a "Note to Reviewers" that says the code should perhaps be updated to use C11 lock-free atomic objects if they are mandated by Issue 8. |
(0003818) geoffclare (manager) 2017-08-17 16:37 |
An additional change that is needed is to add ws_ as a reserved prefix for <termios.h> in the first table in XSH 2.2.2 (after c_, B[0-9], TC). |
(0003820) Clausecker (reporter) 2017-08-31 09:24 |
Attached as sigwinch-proposal.2.txt is an updated version of the proposal. The following changes were made: * As discussed in the telco, ws_xpixel and ws_ypixel were removed from the proposal. * Some typographic errors were corrected. * The faulty example code for tcgetsize() was removed. * An application usage not indicating correct use of tcgetsize() in conjunction with SIGWINCH was added. * The language about the delivery of SIGWINCH on call of tcsetsize() to pseudo-terminals was removed and replaced by more general language. * The prefix ws_ was marked as reserved. * The functions tcsetsize() and tcgetsize() were marked as async-signal-safe. |
(0003854) geoffclare (manager) 2017-09-14 07:42 |
I have attached an updated version of my example program as sigwinch_example.2.c which omits the pixel fields. |
(0003856) nick (manager) 2017-10-05 16:30 edited on: 2017-10-19 15:18 |
Extensions to termios.h ======================= A new subsection named "The winsize structure" is added to the header termios.h right after the section "The termios structure." The winsize Structure --------------------- The <termios.h> header shall define the winsize structure, which shall include at least the following members: unsigned short ws_row rows, in characters. unsigned short ws_col columns, in characters. Furthermore, the list of declared functions shall be amended with the following two entries: int tcgetwinsize(int, struct winsize *); int tcsetwinsize(int, const struct winsize *); The section "CHANGE HISTORY" shall be amended appropriately. Extensions to signal.h ====================== The table of signals shall be amended with the following entry: Signal: SIGWINCH Default Action: I Description: Terminal window size changed. The section "CHANGE HISTORY" shall be amended appropriately. On P201 L6734 (XBD 11.1.4) add tcsetwinsize() to the list of functions, after tcsetpgrp(). Change P1410, L46849-46859 in the DESCRIPTION of open() from: O_TTY_INITIf path identifies a terminal device other than a pseudo-terminal, the to: O_TTY_INITIf path identifies a terminal device other than a pseudo-terminal, the New function "tcgetwinsize" ======================== A new page "tcgetwinsize" shall be added to the list of system interfaces. Its text is analogous to that of tcgetattr and shall be as follows: NAME tcgetwinsize -- get the size of a terminal window SYNOPSIS #include <termios.h> int tcgetwinsize(int fildes, struct winsize *winsize_p); DESCRIPTION The tcgetwinsize() function shall get the terminal window size associated with the terminal referred to by fildes and store it in the winsize structure pointed to by winsize_p. The fildes argument is an open file descriptor associated with a terminal. The winsize_p argument is a pointer to a winsize structure. If the terminal referred to by fildes was opened without O_TTY_INIT and is not a pseudo-terminal, and the terminal window size has not been set by a call to tcsetwinsize(), the terminal window size is unspecified. If the terminal was opened with O_TTY_INIT or is a pseudo-terminal, and the terminal window size has not been set by a call to tcsetwinsize(), the terminal window size shall be set to an appropriate default (see [xref to open()]). If the terminal window size has been set by a call to tcsetwinsize(), the values set by that call shall be returned. RETURN VALUE Upon succesful completion, 0 shall be returned. Otherwise, -1 shall be returned and errno set to indicate the error. ERRORS The tcgetwinsize() function shall fail if: [EBADF] The fildes argument is not a valid file descriptor. [ENOTTY] The file associated with fildes is not a terminal. EXAMPLES #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <signal.h> #include <termios.h> #include <unistd.h> static volatile sig_atomic_t vrow; static volatile sig_atomic_t vcol; static volatile sig_atomic_t newsize; static void winch_handler(int signum) { struct winsize ws; int sav_errno = errno; (void)signum; /* prevent compiler warning that signum is unused */ /* set volatile vars to new winsize, or 0 if unavailable or too large */ if (tcgetwinsize(STDERR_FILENO, &ws) == -1) { vrow = vcol = 0; } else { if (ws.ws_row <= SIG_ATOMIC_MAX && ws.ws_col <= SIG_ATOMIC_MAX) { vrow = ws.ws_row; vcol = ws.ws_col; } else { vrow = vcol = 0; } } newsize = 1; errno = sav_errno; } int main(void) { struct sigaction sa; struct winsize ws; sigset_t winch_set; char inbuf[512]; sa.sa_handler = winch_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGWINCH, &sa, NULL); sigemptyset(&winch_set); sigaddset(&winch_set, SIGWINCH); raise(SIGWINCH); /* gets the initial winsize */ for (;;) { if (fgets(inbuf, sizeof inbuf, stdin) == NULL) { if (feof(stdin)) exit(0); else if (errno == EINTR) continue; else { perror("Error reading stdin"); exit(1); } } else { if (newsize) { /* prevent updates to volatile vars while we read them */ sigprocmask(SIG_BLOCK, &winch_set, NULL); ws.ws_row = vrow; ws.ws_col = vcol; sigprocmask(SIG_UNBLOCK, &winch_set, NULL); newsize = 0; } printf("row = %3hu, col = %3hu\n", ws.ws_row, ws.ws_col); /* process inbuf ... */ } } } APPLICATION USAGE Applications should take care to avoid race conditions and other undefined behavior when calling tcgetwinsize() from signal handlers. A common but incorrect idiom is to establish a signal handler for SIGWINCH from which tcgetwinsize() is called to update a global struct winsize. This usage is incorrect as accessing a struct winsize is not guaranteed to be an atomic operation. Instead, applications should have tcgetwinsize() write to a local structure and copy each member the application is interested in to a global variable of type volatile sig_atomic_t. Furthermore, SIGWINCH should be blocked from delivery while the terminal size is read from these global variables to further avoid race conditions. A simpler alternative, if the application is structured in a suitable way, is just to set a flag in the signal handler and then call tcgetwinsize() (and clear the flag) at an appropriate place in the code if the flag has been set. Multi-threaded applications should avoid the signal handler idiom in general. Instead, it is advised to use sigwait() to wait for the delivery of a SIGWINCH signal. If the terminal window size changes while a process is in the background, it is not notified via SIGWINCH (which is sent only to the foreground process group). Applications can handle this case by calling tcgetwinsize() if the process receives SIGCONT, to check whether the terminal window size changed while the process was stopped. If a background process writes to a terminal and the TOSTOP flag is clear (see [xref to XBD 11.2.5 Local Modes]), the process might not receive SIGTTOU or SIGWINCH signals and thus might not be notified when the terminal window size might have changed. Such processes must periodically poll the current terminal window size if needed. RATIONALE The tcgetwinsize() function is provided to allow applications to query the current terminal window size. This is necessary for applications intended to be run in terminals whose terminal window size can be changed at runtime. Conventionally, a SIGWINCH signal is delivered to a controlling terminal's foreground process group whenever its terminal window size is changed. By installing a signal handler for SIGWINCH, a process can detect the change to the controlling terminal's window size and take action, e.g. by redrawing its user interface to the new size. FUTURE DIRECTIONS None. SEE ALSO tcsetwinsize(), <termios.h> The "CHANGE HISTORY" section shall be filled in appropriately. New function "tcsetwinsize" ======================== A new page "tcsetwinsize" shall be added to the list of system interfaces. Its text is analogous to that of tcsetattr and shall be as follows: NAME tcsetwinsize -- set the size of a terminal window SYNOPSIS #include <termios.h> int tcsetwinsize(int fildes, const struct winsize *winsize_p); DESCRIPTION The tcsetwinsize() function shall set the terminal window size associated with the terminal referred to by the open file descriptor fildes (an open file descriptor associated with a terminal) from the winsize structure referenced by winsize_p. The change shall occur immediately. If the terminal size was changed succesfully, a SIGWINCH shall be delivered to the foreground process group associated with the terminal. No signal shall be delivered if the terminal size was changed to the same value it had before the tcsetwinsize() call. A SIGWINCH may also be delivered to an implementation defined set of other processes. The tcsetwinsize() function shall return successfully if it was able to update all members of the winsize structure associated with the terminal. It is unspecified whether changing the terminal window size causes any changes to the size of the terminal's font. The effect of tcsetwinsize() is undefined if the value of the winsize structure pointed to by winsize_p was not derived from the result of a call to tcgetwinsize() on fildes; an application should modify only fields defined by this volume of POSIX.1-20xx between the call to tcgetwinsize() and tcsetwinsize(), leaving all other fields unmodified. No actions defined by this volume of POSIX.1-20xx, other than a call to tcsetwinsize(), a close of the last file descriptor in the system associated with this terminal device, or an open of this terminal device (using the O_TTY_INIT flag if it is non-zero and the device is not a pseudo-terminal), shall cause the terminal window size to change. If tcsetwinsize() is called from a process which is a member of a background process group on a fildes associated with its controlling terminal:
RETURN VALUE Upon successful completion, 0 shall be returned. Otherwise, -1 shall be returned, the terminal window size shall not be changed, and errno shall be set to indicate the error. ERRORS The tcsetwinsize() function shall fail if: [EBADF] The fildes argument is not a valid file descriptor. [EIO] The process group of the writing process is orphaned, the calling thread is not blocking SIGTTOU, and the process is not ignoring SIGTTOU. [ENOTTY] The file associated with fildes is not a terminal. The tcsetwinsize() function may fail if: [EINVAL] An attempt was made to change an attribute represented in the winsize structure to an unsupported value. EXAMPLES None. APPLICATION USAGE If the terminal window of a pseudo terminal is resized, the attached master process should invoke tcsetwinsize() to relay the new terminal window size to the foreground process group. If a process attached to the slave of a pseudo-terminal calls tcsetwinsize(), the attached master process should attempt to change the screen to reflect the new size. RATIONALE This standard does not mention the ws_xpixel and ws_ypixel fields that appear in the winsize structure of some historical implementations. With current hardware, it is not obvious that the unsigned short type used for these fields is sufficient and no uses of these fields in portable code were found. However, since these and other fields may be included in the winsize structure, the standard requires that applications use tcgetwinsize() to initialize any fields that may be provided by an implementation before setting the ws_cols and ws_rows fields using tcsetwinsize() to avoid unintentionally destroying data in other fields in this structure. FUTURE DIRECTIONS None. SEE ALSO tcgetwinsize(), <termios.h> The "CHANGE HISTORY" section shall be filled in appropriately. New reserved prefix ws_ ======================= To the first table in §2.2.2, add ws_ as a reserved prefix for the header <termios.h> (after c_, B[0-9], TC). tcgetwinsize() and tcsetwinsize() are async-signal-safe ================================================= To the list of async-signal-safe functions in §2.4.3, add tcgetwinsize() and tcsetwinsize(). |
(0003857) Clausecker (reporter) 2017-10-16 19:28 |
I'm terribly sorry to reopen this. It turns out (as I didn't knew before) that QNX already specifies tcgetsize with an incompatible signature: http://www.qnx.com/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Ft%2Ftcgetsize.html [^] It might perhaps be a good idea to change the function names to something like tcgetwinsize() and tcsetwinsize() to avoid this unfortunate name collision before the function has been set into stone. |
(0003858) Clausecker (reporter) 2017-10-16 19:30 |
See previous comment; QNX already has tcgetsize() and tcsetsize() with an incompatible signature. It might be a good idea to avoid the foreseeable conflict by either adopting the QNX signature or by renaming the POSIX function. |
(0003859) geoffclare (manager) 2017-10-17 14:07 |
I think it's not just the function signatures that are different in QNX. Their man page for tcsetsize() says it give an EACCES error if "The filedes argument isn't associated with a controlling terminal", whereas we have made the terminal access semantics for tcsetsize() the same as for tcsetattr(), i.e. the SIGTTOU and EIO stuff. Therefore I would prefer that we rename to tcgetwinsize() and tcsetwinsize(). I think I like these names better anyway, as they go with the winsize structure tag. |
(0003860) Clausecker (reporter) 2017-10-17 18:59 |
I agree with this proposal. I am again very sorry for bringing this up again, the QNX functions didn't turn up in my initial search for these function names. Another good reason for not adopting the QNX signatures is that they do not easily extend to reporting the terminal resolution in pixels if that is desired by implementations or a future issue of IEEE 1003.1. |
(0003862) geoffclare (manager) 2017-10-19 15:20 |
Note: 0003856 has been edited to change the function names to tcgetwinsize() and tcsetwinsize(). |
(0003865) egmont (reporter) 2017-10-20 20:26 edited on: 2017-10-20 20:37 |
Allow me please to share a few thoughts/questions regarding ws_xpixel/ws_ypixel. I'm glad these didn't make it to the standard for now; if you ever plan to add them then please get back here and consider these issues. - Most graphical terminal emulators have some padding (usually 1px) around the character cells. This is I believe both for aesthetical reasons as well better/easier handling of mouse dragging outside the area etc. Rxvt-unicode, pterm (putty) and st (suckless) set ws_[xy]pixel without this value, xterm adds the padding too. (See the matrix at https://bugzilla.gnome.org/show_bug.cgi?id=782576 [^] .) Which one should be the right behavior and why? - xterm actually does not only add the padding, but also the scrollbar's width to ws_xpixel. Is this correct then? - How about other graphical UI elements? E.g. what if xterm had a tab bar (like gnome-terminal, konsole etc. have), should it add that too? What if it used CSD (client-side window decoration), would that also count? - If the answer was "yes" throughout the previous questions, how about tiling (a.k.a. paned) emulators such as Terminator and Tilix? - If it's only the cell's pixels (not even the padding) then what's the point in storing the entire window's dimensions and worrying about 16-bit overflow, rather than introducing new fields for a single cell's dimensions (as shorts)? - Continuing the previous question, kitty ( https://github.com/kovidgoyal/kitty [^] ) is the only terminal emulator I've seen so far that allows continuous resize, and splits the "extra" space among some of its character cells, resulting in certain cells being 1px taller or wider than others. Would this be the reason / use case for denoting the entire terminal emulator's dimensions? Wouldn't it cause problems that it's unknown how those extra pixels are distributed? - What about headless terminal emulators, such as the libvterm library ( https://launchpad.net/libvterm [^] ), or screen or tmux in detached mode? - What about terminal emulators that can have multiple views, potentially at different pixel sizes? E.g. konsole allows to "split view" and zoom independently, or screen and tmux allow to attach from multiple terminal emulators that potentially have different fonts, or VTE (gnome-terminal and friends) if it ever addresses https://bugzilla.gnome.org/show_bug.cgi?id=103770 [^] . - What about cool-retro-term ( https://github.com/Swordfish90/cool-retro-term [^] ) where charcells aren't even rectangles? - What about high DPI screens where some scaling is applied? I'm not familiar with those, but as far as I know, there are at least 2 (pre-scaling and post-scaling), maybe even 3 definitions of "pixel". Which one to use? Taking one step back and looking at the broader picture: What's the purpose of these variables? What use cases do you have in mind? Unless these questions are clearly answered, unless a clear intent is seen and clear semantics is defined for these variables, no longer allowing terminal emulators to use these fields inconsistently, there's hardly any point standardizing this feature. Thanks in advance for considering these questions whenever you get to standardizing ws_[xy]pixels! |
(0004829) geoffclare (manager) 2020-04-23 13:45 |
When applying this bug I did not follow the instruction:A new subsection named "The winsize structure" is added to the header termios.h right after the section "The termios structure."to the letter. This is because several subsections following "The termios structure" relate to fields in the termios structure. Instead, I added "The winsize Structure" just before the "Attribute Selection" heading. |
Issue History | |||
Date Modified | Username | Field | Change |
2017-06-19 16:41 | Clausecker | New Issue | |
2017-06-19 16:41 | Clausecker | File Added: sigwinch-proposal.txt | |
2017-06-19 16:41 | Clausecker | Name | => Robert Clausecker |
2017-06-19 16:41 | Clausecker | Organization | => Fraunhofer Fokus |
2017-06-19 16:41 | Clausecker | Section | => termios.h, signal.h, 2.4.3 "Signal Actions", 11.2 "Parameters that Can be Set", new sections tcgetsize and tcsetsize |
2017-06-19 16:41 | Clausecker | Page Number | => 414, 333, 494, 212 |
2017-06-19 16:41 | Clausecker | Line Number | => 13877, 11115, 16845–16879, 7040 |
2017-06-19 17:32 | shware_systems | Note Added: 0003786 | |
2017-06-19 17:33 | shware_systems | Note Edited: 0003786 | |
2017-06-19 18:06 | EdSchouten | Note Added: 0003787 | |
2017-06-19 18:11 | shware_systems | Note Added: 0003788 | |
2017-06-19 18:43 | Clausecker | Note Added: 0003789 | |
2017-06-20 09:22 | geoffclare | Note Added: 0003791 | |
2017-06-22 10:36 | shware_systems | Note Added: 0003797 | |
2017-06-22 15:04 | geoffclare | Relationship added | related to 0001053 |
2017-06-22 15:46 | shware_systems | Note Edited: 0003786 | |
2017-06-22 16:45 | geoffclare | Note Added: 0003798 | |
2017-06-22 16:52 | Don Cragun | Note Added: 0003799 | |
2017-06-22 20:53 | Clausecker | Note Added: 0003800 | |
2017-06-29 09:12 | geoffclare | File Added: sigwinch_example.c | |
2017-06-29 09:20 | geoffclare | Note Added: 0003804 | |
2017-08-17 15:18 | shware_systems | Note Edited: 0003786 | |
2017-08-17 15:24 | shware_systems | Note Edited: 0003786 | |
2017-08-17 16:37 | geoffclare | Note Added: 0003818 | |
2017-08-31 09:19 | Clausecker | File Added: sigwinch-proposal.2.txt | |
2017-08-31 09:24 | Clausecker | Note Added: 0003820 | |
2017-09-14 07:41 | geoffclare | File Added: sigwinch_example.2.c | |
2017-09-14 07:42 | geoffclare | Note Added: 0003854 | |
2017-10-05 16:30 | nick | Note Added: 0003856 | |
2017-10-05 16:31 | nick | Interp Status | => --- |
2017-10-05 16:31 | nick | Final Accepted Text | => See Note: 0003856 |
2017-10-05 16:31 | nick | Status | New => Resolution Proposed |
2017-10-05 16:31 | nick | Resolution | Open => Accepted As Marked |
2017-10-05 16:32 | nick | Tag Attached: issue8 | |
2017-10-05 16:33 | nick | Status | Resolution Proposed => Resolved |
2017-10-16 19:28 | Clausecker | Note Added: 0003857 | |
2017-10-16 19:30 | Clausecker | Note Added: 0003858 | |
2017-10-16 19:30 | Clausecker | Status | Resolved => Under Review |
2017-10-16 19:30 | Clausecker | Resolution | Accepted As Marked => Reopened |
2017-10-17 14:07 | geoffclare | Note Added: 0003859 | |
2017-10-17 18:59 | Clausecker | Note Added: 0003860 | |
2017-10-17 18:59 | Clausecker | Note Added: 0003861 | |
2017-10-17 18:59 | Clausecker | Note Deleted: 0003861 | |
2017-10-19 15:18 | geoffclare | Note Edited: 0003856 | |
2017-10-19 15:20 | geoffclare | Note Added: 0003862 | |
2017-10-19 15:21 | geoffclare | Status | Under Review => Resolved |
2017-10-19 15:21 | geoffclare | Resolution | Reopened => Accepted As Marked |
2017-10-20 20:16 | egmont | Note Added: 0003864 | |
2017-10-20 20:26 | egmont | Note Added: 0003865 | |
2017-10-20 20:26 | egmont | Note Deleted: 0003864 | |
2017-10-20 20:28 | egmont | Note Edited: 0003865 | |
2017-10-20 20:31 | egmont | Note Edited: 0003865 | |
2017-10-20 20:37 | egmont | Note Edited: 0003865 | |
2019-02-25 16:46 | nick | Relationship added | related to 0001185 |
2020-04-23 13:45 | geoffclare | Note Added: 0004829 | |
2020-04-23 13:45 | geoffclare | Status | Resolved => Applied |
2024-06-11 09:09 | agadmin | Status | Applied => Closed |
Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group |