View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0001966 | 1003.1(2024)/Issue8 | Shell and Utilities | public | 2025-12-21 11:17 | 2026-02-06 09:11 |
| Reporter | stephane | Assigned To | |||
| Priority | normal | Severity | Objection | Type | Clarification Requested |
| Status | Interpretation Required | Resolution | Accepted As Marked | ||
| Name | Stephane Chazelas | ||||
| Organization | |||||
| User Reference | |||||
| Section | current/previous job in basedefs, jobs, fg, bg utilities | ||||
| Page Number | (page or range of pages) | ||||
| Line Number | (Line or range of lines) | ||||
| Interp Status | Pending | ||||
| Final Accepted Text | 0001966:0007371 | ||||
| Summary | 0001966: Current/previous job definition scattered and ambiguous | ||||
| Description | POSIX defines the "current job" as: > In the context of job control, the job that will be used as > the default for the fg or bg utilities. (https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/basedefs/V1_chap03.html#tag_03_93). With the fg utility specification stating: > no job_id operand is given, the job_id for the job that was > most recently suspended, placed in the background, or run as a > background job shall be used. (https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/utilities/fg.html) Previous job is defined as: > In the context of job control, the job that will be used as > the default for the fg or bg utilities if the current job > exits. (https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/V1_chap03.html#tag_03_286) We however need to refer to the "jobs" utility specification to make some sense out of that: > The character '+' identifies the job that would be used as a > default for the fg or bg utilities; this job can also be > specified using the job_id %+ or "%%". The character '-' > identifies the job that would become the default if the > current default job were to exit; this job can also be > specified using the job_id %-. For other jobs, this field is a > <space>. At most one job can be identified with '+' and at > most one job can be identified with '-'. If there is any > suspended job, then the current job shall be a suspended job. > If there are at least two suspended jobs, then the previous > job also shall be a suspended job. (https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/utilities/jobs.html) That suggests "the job_id for the job that was most recently suspended, placed in the background, or run as a background job shall be used" from the "current job" definition is to be interpreted as: 1. the most recently suspend job if there are suspended jobs 2. if not, the job most recently "placed in the background" (whatever that means) if there are some. 3. if not the job most recently started in background. As far I know, the only ways to "place" a job in the background are to suspend them whilst they are in foreground or start them in background in the first place, so there are several ways to interpret that "2" above: a) 3 is redundant but it's to emphasis that it's the time of last suspend (whilst in foreground, or not, to be clarified) that's important for those jobs that have been suspended. b) it's to say that jobs that have ever been suspended (have ever been in foreground before) take precedence over jobs that were started in background in the first place and were never suspended. c) maybe "resumed in background" (by way of bg or any other way SIGCONT is delivered) was intended instead of "placed in background". The Rationale there also has: > The job control features provided by bg, fg, and jobs are > based on the KornShell. The standard developers examined the > characteristics of the C shell versions of these utilities and > found that differences exist. Despite widespread use of the C > shell, the KornShell versions were selected for this volume of > POSIX.1-2024 to maintain a degree of uniformity with the rest > of the KornShell features selected (such as the very popular > command line editing features). However, testing ksh88 from Solaris 11.4's /usr/xpg4/bin/sh and ksh93u+m/1.0.8 2024-01-01, those are clearly not compliant, as $ sleep 1001 ^Z[1] + Stopped sleep 1001 $ sleep 1002 & [2] 20308 $ jobs [2] + Running sleep 1002 & [1] - Stopped sleep 1001 The suspended job is not made the current job, whilst that's the part that is clearly unambiguous in the spec in the description of the jobs utility. In practice, I see a lot of variation between implementations, and I don't think I've come across one that fully implements any of the interpretations listed above. | ||||
| Desired Action | Change the definition of "current job" to: Either make (carry on making) ksh non-compliant with: > If there are any suspended job, the most recently suspended > job. If not, one of the jobs running in background. It's > unspecified whether that's the most recently started, most > recently suspended (in the past) or most recently resumed or > combination thereof. Or to also account for ksh (mksh is yet different from ksh88/ksh93) with: > If there are any suspended job, then the current job shall > be the most recently suspended job as long as it's still in > a suspended state and no other job was started since it was > last suspended. Otherwise, it is unspecified which job shall > be the current job. Adding a: > users may refer to the output of the jobs utility to know > which is the current and previous job With a reference to the jobs utility specification could be useful. Maybe clarify the definition of "previous job" to something like: > what the current job would be in the absence of whichever job > is currently appointed as the current job. Then update the "jobs" / "fg" / "bg" specification to refer to those definitions. And either remove the jobs utility rationale section about the specification being based on the Korn shell rather than C shell or clarify which of the C / Korn shell behaviours were selected in the POSIX specification. | ||||
| Tags | tc1-2024 | ||||
|
|
Interpretation response ------------------------ The standard is unclear on this issue, and no conformance distinction can be made between alternative implementations based on this. This is being referred to the sponsor. Rationale: ------------- There is a conflict between the description of <current> in the STDOUT section of the jobs utility and the description of the job_id operand for the fg and bg utilities. Notes to the Editor (not part of this interpretation): ------------------------------------------------------- On page 2666 line 87729 section bg, change: If no job_id operand is given, the most recently suspended job shall be used. to: If no job_id operand is given, the job_id for the job that was most recently suspended, placed in the background, or run as a background job shall be used, except that if there is any suspended job: On page 2928 line 97725 section fg, change: If no job_id operand is given, the job_id for the job that was most recently suspended, placed in the background, or run as a background job shall be used. to: If no job_id operand is given, the job_id for the job that was most recently suspended, placed in the background, or run as a background job shall be used, except that if there is any suspended job: On page 3022 line 101144 section jobs, delete: If there is any suspended job, then the current job shall be a suspended job. If there are at least two suspended jobs, then the previous job also shall be a suspended job. |
|
|
Re: 0001959:0007370 > the job that was most recently suspended, placed in the > background, or run as a background job We may want to clarify what "placed in the background" means. AFAIK, the only ways (as already noted in the bug description) to "place" a job in the background are to "run it as a background job" and suspend them whilst they are in foreground, which here would seem to make that "placed in background" redundant. The "bg" utility is to "resume, still in background" (send SIGCONT to the process group), while "fg" puts a job in foreground, resumes it if suspended and waits for one of the processes in the job to terminate or be suspended again. I've tried to check whether any shell was compliant to this new specification and among mksh, yash, bash, zsh, dash, ksh93, only ksh93 seems to be as it's the only one that seems to maintain the job table in terms of priority for that "current job" (and diverges from all other shells and by not always priotising suspended jobs). dash (and presumably other ash-based shells) also does that ordering, but since it prioritises suspended jobs, as was the spirit of job control as originally implemented on BSDs, (and if not makes "bg" alone less useful for instance), once resumed in background, that background job remains the current job: $ dash $ sleep 1h & $ sleep 2h ^Z[2] + Stopped sleep 2h $ sleep 3h & $ jobs [2] + Stopped sleep 2h [3] - Running sleep 3h [1] Running sleep 1h Stopped job is current as allowed (previously required) by the proposed text. $ bg [2] sleep 2h $ jobs [2] + Running sleep 2h [3] - Running sleep 3h [1] Running sleep 1h %2 still current job which sounds like is not compliant to the new text unless the: > the job that was most recently suspended, placed in the > background, or run as a background job shall be used. Is to be understood as: 1. most recently suspended job if any of the jobs have ever been suspended. 2. If not: most recently "placed in background" if any of the jobs have even been "placed in background". 3. If not: most recently run as a background job. (In which case ksh93 would not be compliant) as otherwise %3 would need to be the current job as it was "placed in the background" (or "run as a background job") after %2 was suspended. In any case, bash, zsh, mksh, yash are not compliant (because they don't order that list or some other reasons). In other words, I suggested two resolutions, one that would (AFAICT) make all shells but ksh compliant and was more in the spirit of the current specification and another one that would make all shells compliant, but instead, the currently proposed resolution makes all shells but ksh non-compliant, ksh being the one that goes against the fundamental principle that suspended jobs should be prioritised for the current/previous job appointment. IMO, that's not OK, because it doesn't help. First, IMO, POSIX specifying interactive use behaviour has little benefit. It's invaluable to standardise the shell language to write portable scripts, but trying to tightly specify user interaction is more likely to hinder progress than anything. One could argue that specifying interactive use experience means users from one system/shell can expect not to be disoriented when jumping to another system/shell, but in this instance, the resolution makes an important point unspecified and on the other hand mandates things that are less important and in practice vary between implementations. If there's a suspended job, people expect that to be the current job as that's what most shells do and even what POSIX currently requires. ksh breaks that expectation. On the other end, what rules determine which job will become the current job once the current and previous jobs have terminated or all jobs have been resumed matters less, as nobody will manage to remember those rules and compute them mentally so would need to refer to the "jobs" output to know which it is or would refer to jobs by their number or search string instead. About the "previous job" definition: > In the context of job control, the job that will be used as >the default for the fg or bg utilities if the current job exits A process can "exit", by way of the exit() function for instance, but what does it mean for a "job" to exit? For instance, (sleep 60 & sleep 1) Starts a foreground job with a process running sleep 60, one running sleep 1 and possibly a shell one waiting for sleep 1, After one second, the one running sleep 1 (and the shell one waiting for it if any) exit()s, while the one running sleep 60 is still running. However, as far as the interactive shell that started that job is concerned, that job is gone as there's only one process in that job it's waiting for (the one that runs the subshell if any and possibly subsequently sleep 1 or waited for that sleep 1 in those shells that implement subshells as child processes and don't optimise out the fork for sleep 1). My: > what the current job would be in the absence of whichever job > is currently appointed as the current job. Was attempting to clarify it, and avoids having to define what it means for a job to "exit" though still leaves it unclear what makes a job "absent" or "present". Note that even "running job" or "suspended job" are potentially ambiguous as some processes in the job could be suspended and some running, but maybe that's for another bug. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2025-12-21 11:17 | stephane | New Issue | |
| 2026-01-06 10:04 | geoffclare | Project | 1003.1(2013)/Issue7+TC1 => 1003.1(2024)/Issue8 |
| 2026-02-05 17:20 | geoffclare | Note Added: 0007371 | |
| 2026-02-05 17:21 | geoffclare | Status | New => Interpretation Required |
| 2026-02-05 17:21 | geoffclare | Resolution | Open => Accepted As Marked |
| 2026-02-05 17:21 | geoffclare | Interp Status | => Pending |
| 2026-02-05 17:21 | geoffclare | Final Accepted Text | => 0001966:0007371 |
| 2026-02-05 17:21 | geoffclare | Tag Attached: tc1-2024 | |
| 2026-02-06 09:11 | stephane | Note Added: 0007372 |