Skip to content

Commit 15a6e3c

Browse files
committed
Support: Make Wait's SecondsToWait be std::optional [NFC]
I found the interaction between SecondsToWait and WaitUntilChildTerminates confusing. Rather than have a boolean to ignore the value of SecondsToWait, combine these into one Optional parameter.
1 parent f532b02 commit 15a6e3c

File tree

5 files changed

+45
-42
lines changed

5 files changed

+45
-42
lines changed

llvm/include/llvm/Support/Program.h

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -205,22 +205,22 @@ namespace sys {
205205
/// \li 0 if the child process has not changed state.
206206
/// \note Users of this function should always check the ReturnCode member of
207207
/// the \see ProcessInfo returned from this function.
208-
ProcessInfo Wait(
209-
const ProcessInfo &PI, ///< The child process that should be waited on.
210-
unsigned SecondsToWait, ///< If non-zero, this specifies the amount of
211-
///< time to wait for the child process to exit. If the time expires, the
212-
///< child is killed and this function returns. If zero, this function
213-
///< will perform a non-blocking wait on the child process.
214-
bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits
215-
///< until child has terminated.
216-
std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
217-
///< string instance in which error messages will be returned. If the
218-
///< string is non-empty upon return an error occurred while invoking the
219-
///< program.
220-
std::optional<ProcessStatistics> *ProcStat =
221-
nullptr ///< If non-zero, provides
222-
/// a pointer to a structure in which process execution statistics will be
223-
/// stored.
208+
ProcessInfo
209+
Wait(const ProcessInfo &PI, ///< The child process that should be waited on.
210+
std::optional<unsigned> SecondsToWait, ///< If std::nullopt, waits until
211+
///< child has terminated.
212+
///< If a value, this specifies the amount of time to wait for the child
213+
///< process to exit. If the time expires, the child is killed and this
214+
///< function returns. If zero, this function will perform a non-blocking
215+
///< wait on the child process.
216+
std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
217+
///< string instance in which error messages will be returned. If the
218+
///< string is non-empty upon return an error occurred while invoking the
219+
///< program.
220+
std::optional<ProcessStatistics> *ProcStat =
221+
nullptr ///< If non-zero, provides
222+
/// a pointer to a structure in which process execution statistics will
223+
/// be stored.
224224
);
225225

226226
/// Print a command argument, and optionally quote it.

llvm/lib/Support/Program.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
4242
AffinityMask)) {
4343
if (ExecutionFailed)
4444
*ExecutionFailed = false;
45-
ProcessInfo Result =
46-
Wait(PI, SecondsToWait, /*WaitUntilTerminates=*/SecondsToWait == 0,
47-
ErrMsg, ProcStat);
45+
ProcessInfo Result = Wait(
46+
PI, SecondsToWait == 0 ? std::nullopt : std::optional(SecondsToWait),
47+
ErrMsg, ProcStat);
4848
return Result.ReturnCode;
4949
}
5050

llvm/lib/Support/Unix/Program.inc

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -384,17 +384,19 @@ pid_t(llvm::sys::wait4)(pid_t pid, int *status, int options,
384384
}
385385
#endif
386386

387-
ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
388-
bool WaitUntilTerminates, std::string *ErrMsg,
387+
ProcessInfo llvm::sys::Wait(const ProcessInfo &PI,
388+
std::optional<unsigned> SecondsToWait,
389+
std::string *ErrMsg,
389390
std::optional<ProcessStatistics> *ProcStat) {
390391
struct sigaction Act, Old;
391392
assert(PI.Pid && "invalid pid to wait on, process not started?");
392393

393394
int WaitPidOptions = 0;
394395
pid_t ChildPid = PI.Pid;
395-
if (WaitUntilTerminates) {
396-
SecondsToWait = 0;
397-
} else if (SecondsToWait) {
396+
bool WaitUntilTerminates = false;
397+
if (!SecondsToWait) {
398+
WaitUntilTerminates = true;
399+
} else if (*SecondsToWait != 0) {
398400
// Install a timeout handler. The handler itself does nothing, but the
399401
// simple fact of having a handler at all causes the wait below to return
400402
// with EINTR, unlike if we used SIG_IGN.
@@ -403,9 +405,11 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
403405
sigemptyset(&Act.sa_mask);
404406
sigaction(SIGALRM, &Act, &Old);
405407
// FIXME The alarm signal may be delivered to another thread.
406-
alarm(SecondsToWait);
407-
} else if (SecondsToWait == 0)
408+
409+
alarm(*SecondsToWait);
410+
} else {
408411
WaitPidOptions = WNOHANG;
412+
}
409413

410414
// Parent process: Wait for the child process to terminate.
411415
int status;

llvm/lib/Support/Windows/Program.inc

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -408,24 +408,21 @@ ErrorOr<std::wstring> sys::flattenWindowsCommandLine(ArrayRef<StringRef> Args) {
408408
return std::wstring(CommandUtf16.begin(), CommandUtf16.end());
409409
}
410410

411-
ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
412-
bool WaitUntilChildTerminates, std::string *ErrMsg,
411+
ProcessInfo sys::Wait(const ProcessInfo &PI,
412+
std::optional<unsigned> SecondsToWait,
413+
std::string *ErrMsg,
413414
std::optional<ProcessStatistics> *ProcStat) {
414415
assert(PI.Pid && "invalid pid to wait on, process not started?");
415416
assert((PI.Process && PI.Process != INVALID_HANDLE_VALUE) &&
416417
"invalid process handle to wait on, process not started?");
417-
DWORD milliSecondsToWait = 0;
418-
if (WaitUntilChildTerminates)
419-
milliSecondsToWait = INFINITE;
420-
else if (SecondsToWait > 0)
421-
milliSecondsToWait = SecondsToWait * 1000;
418+
DWORD milliSecondsToWait = SecondsToWait ? *SecondsToWait * 1000 : INFINITE;
422419

423420
ProcessInfo WaitResult = PI;
424421
if (ProcStat)
425422
ProcStat->reset();
426423
DWORD WaitStatus = WaitForSingleObject(PI.Process, milliSecondsToWait);
427424
if (WaitStatus == WAIT_TIMEOUT) {
428-
if (SecondsToWait) {
425+
if (*SecondsToWait > 0) {
429426
if (!TerminateProcess(PI.Process, 1)) {
430427
if (ErrMsg)
431428
MakeErrMsg(ErrMsg, "Failed to terminate timed-out program");

llvm/unittests/Support/ProgramTest.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,28 +228,30 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {
228228

229229
unsigned LoopCount = 0;
230230

231-
// Test that Wait() with WaitUntilTerminates=true works. In this case,
231+
// Test that Wait() with SecondsToWait=std::nullopt works. In this case,
232232
// LoopCount should only be incremented once.
233233
while (true) {
234234
++LoopCount;
235-
ProcessInfo WaitResult = llvm::sys::Wait(PI1, 0, true, &Error);
235+
ProcessInfo WaitResult =
236+
llvm::sys::Wait(PI1, /*SecondsToWait=*/std::nullopt, &Error);
236237
ASSERT_TRUE(Error.empty());
237238
if (WaitResult.Pid == PI1.Pid)
238239
break;
239240
}
240241

241242
EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1";
242243

243-
ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(), {}, 0, &Error,
244+
ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(),
245+
/*Redirects*/ {}, /*MemoryLimit*/ 0, &Error,
244246
&ExecutionFailed);
245247
ASSERT_FALSE(ExecutionFailed) << Error;
246248
ASSERT_NE(PI2.Pid, ProcessInfo::InvalidPid) << "Invalid process id";
247249

248250
// Test that Wait() with SecondsToWait=0 performs a non-blocking wait. In this
249-
// cse, LoopCount should be greater than 1 (more than one increment occurs).
251+
// case, LoopCount should be greater than 1 (more than one increment occurs).
250252
while (true) {
251253
++LoopCount;
252-
ProcessInfo WaitResult = llvm::sys::Wait(PI2, 0, false, &Error);
254+
ProcessInfo WaitResult = llvm::sys::Wait(PI2, /*SecondsToWait=*/0, &Error);
253255
ASSERT_TRUE(Error.empty());
254256
if (WaitResult.Pid == PI2.Pid)
255257
break;
@@ -277,8 +279,8 @@ TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) {
277279
std::string Error;
278280
bool ExecutionFailed;
279281
int RetCode =
280-
ExecuteAndWait(Executable, argv, getEnviron(), {}, /*secondsToWait=*/1, 0,
281-
&Error, &ExecutionFailed);
282+
ExecuteAndWait(Executable, argv, getEnviron(), {}, /*SecondsToWait=*/1,
283+
/*MemoryLimit*/ 0, &Error, &ExecutionFailed);
282284
ASSERT_EQ(-2, RetCode);
283285
}
284286

@@ -423,7 +425,7 @@ TEST_F(ProgramEnvTest, TestLockFile) {
423425
std::this_thread::sleep_for(std::chrono::milliseconds(100));
424426

425427
ASSERT_NO_ERROR(fs::unlockFile(FD1));
426-
ProcessInfo WaitResult = llvm::sys::Wait(PI2, 5 /* seconds */, true, &Error);
428+
ProcessInfo WaitResult = llvm::sys::Wait(PI2, /*SecondsToWait=*/5, &Error);
427429
ASSERT_TRUE(Error.empty());
428430
ASSERT_EQ(0, WaitResult.ReturnCode);
429431
ASSERT_EQ(WaitResult.Pid, PI2.Pid);

0 commit comments

Comments
 (0)