Negative exit value with WEXITSTATUS - fork

I have a child process that is designed to exit under certain conditions, I have used exit(-2). But after calling WEXITSTATUS the value is around 256. If I use exit(2) the proper value is returned by WEXITSTATUS. Any reason why using a negative value in the exit call is doing this?

Related

How can one know if a process in Windows has exited or not?

I have an open process handle and PID of the process. Can I use this information to get status of the process if it has exited or not?
The process ID is fairly useless. It's the kind of crutch you'd be forced to use when targeting POSIX, for example.
It's the process handle that is valuable. You can either wait on the process handle using WaitForSingleObject, for example, or ask for the process' exit code with a call to GetExitCodeProcess.
Either API call is capable of reporting whether the process has terminated or not. Assuming that hProcess is the process handle, the following two snippets produce a value that indicates whether the process has terminated:
bool terminated = ::WaitForSingleObject(hProcess, 0) == WAIT_OBJECT_0;
DWORD exit_code{};
bool terminated = ::GetExitCodeProcess(hProcess, &exit_code) &&
(exit_code != STILL_ACTIVE);
Note that the first option is more robust. The second option cannot distinguish between a process that's still running, and a process that has terminated but set the exit code to a value of STILL_ACTIVE (259).

How is CopyFileEx's pbCancel parameter safe?

There are several questions posted (like Send flag to cancel CopyFileEx after it has started) that reference the ability to use the pbCancel parameter of the Win32 CopyFileEx() function to cancel an in-progress copy. What is not clear to me, is why is it safe to set that boolean in another thread without any sort of synchronization mechanism (mutex, etc.)? This functionality is really only useful if another thread sets that boolean to true, as CopyFileEx() blocks until the file copy is finished.
Is this relying on a peculiarity of the Windows platform?
in case simply set boolean by sense variable (which can be 0 or not 0) without any connection with other data - not need any synchronization - for what ?!
one thread set variable to true, another thread read from variable or 0 or not 0. even if you do write and read to variable in critical section - what this change ? nothing ! thread which will be read - anyway load or 0 or not 0 from variable.
synchronization need in another cases. usually when we write to another memory locations, before store true in variable, and want that after another thread read true from variable - all another memory modification will be visible already. but in case cancel callback - no any another data
or if we write complex data to variable (not only or 0 or not 0) and this write not atomic - synchronization need for prevent read partial state. but here impossible any "partial state" by design
For those who not understand:
no matter are write to or read from pbCancel will be atomic.
in any case finally some value will be read from pbCancel.
if this value will be interpreted as TRUE during the copy operation, the operation is canceled. Otherwise, the copy operation will continue to completion.
If this flag is set to TRUE during the copy operation, the operation is canceled. Otherwise, the copy operation will continue to
completion.
even if some "transient state" will be read - and so what -any way this value will be used in if/else expression and as result copy operation will be canceled or continue.
Nowhere is not specified (and this contradicts common sense) that a strict checking of 0 (false) and 1(true) will be performed and in case of any other value there will be an exception or UB.
on the contrary - it is clearly indicated that Otherwise (ie flag not set to TRUE), the copy operation will continue to completion.. no any words about exception, UB, etc
if look on declaration of CopyFileExW, here visible in more details how pbCancel value is interpreted:
_When_(pbCancel != NULL, _Pre_satisfies_(*pbCancel == FALSE))
_Inout_opt_ LPBOOL pbCancel,
so check is (and this is most native)
if (pbCancel == NULL || *pbCancel == FALSE)
// continue copy
else
// cancel copy
here no any "transient state". here or 0 or not 0. even if you write 1 to pbCancel but another thread read from it say 0x5FD38FCA - this will be interpreted as TRUE and copy operation will be canceled.
anyway - if you write true (in strict sense 1) to variable - another thread sooner or later read 1 from this variable. do this in critical section - nothing change - again only sooner or later another thread read this value. not faster.

tarantool how to handle lua errors outside the fiber

I am wondering, how can i set callback on fiber error throw.
example:
local fiber = require("fiber")
local status = 0 --in my case stored in db
local function time_consuming()
lua_error
status = 0
end
function external_api_function()
if status == 1 then return "already running" end
status = 1
fiber.create(time_consuming)
return "started"
end
so i want to set status to 0 if time_consuming function falls. Is where any way to catch it?
I think about checking fiber:status on next api visit. Or create a watchdog for fiber, if i want status to be valid. This will work for me, but seems like not the best solution.
There are multiple ways to achieve your goal.
Within your example both fibers (main and time_consuming task) share the same scope - status variable. If you change the value of the status variable in the child fiber, parent fiber will see an update. You can check this using simple snippet:
status = 1
fiber.create(function() status = 0 end)
print(status) -- 0
Now, to catch an exception, use pcall function. It accepts a function as a first argument, calls it and returns status as a first value following one or more function results. There is also xpcall function if you want to analyse the error being caught. It takes error handler as a second argument.
With pcall you may change your time_consuming function like this:
local function time_consuming()
local ok = pcall(function() lua_error end)
if not ok then
status = 0
end
end
and status will successfully updated if lua_error fails.
But usually I consider this as a bad practice. If more fibers share the same state, it may become difficult to maintain due to uncertainty of the order of fiber execution. So for more reliable solution you may want to use interfiber communication primitives aka channels. You will be able to explicitly ask child fiber to tell you its execution status whether it succeed or not using channel:put() and channel:get() function. See documentation for examples.

How to check if a process started in the background still running?

It looks like if you create a subprocess via exec.Cmd and Start() it, the Cmd.Process field is populated right away, however Cmd.ProcessState field remains nil until the process exits.
// ProcessState contains information about an exited process,
// available after a call to Wait or Run.
ProcessState *os.ProcessState
So it looks like I can't actually check the status of a process I Start()ed while it's still running?
It makes no sense to me ProcessState is set when the process exits. There's an ProcessState.Exited() method which will always return true in this case.
So I tried to go this route instead: cmd.Process.Pid field exists right after I cmd.Start(), however it looks like os.Process doesn't expose any mechanisms to check if the process is running.
os.FindProcess says:
On Unix systems, FindProcess always succeeds and returns a Process for the given pid, regardless of whether the process exists.
which isn't useful –and it seems like there's no way to go from os.Process to an os.ProcessState unless you .Wait() which defeats the whole purpose (I want to know if the process is running or not before it has exited).
I think you have two reasonable options here:
Spin off a goroutine that waits for the process to exit. When the wait is done, you know the process exited. (Positive: pretty easy to code correctly; negative: you dedicate an OS thread to waiting.)
Use syscall.Wait4() on the published Pid. A Wait4 with syscall.WNOHANG set returns immediately, filling in the status.
It might be nice if there were an exported os or cmd function that did the Wait4 for you and filled in the ProcessState. You could supply WNOHANG or not, as you see fit. But there isn't.
The point of ProcessState.Exited() is to distinguish between all the various possibilities, including:
process exited normally (with a status byte)
process died due to receiving an unhandled signal
See the stringer for ProcessState. Note that there are more possibilities than these two ... only there seems to be no way to get the others into a ProcessState. The only calls to syscall.Wait seem to be:
syscall/exec_unix.go: after a failed exec, to collect zombies before returning an error; and
os/exec_unix.go: after a call to p.blockUntilWaitable().
If it were not for the blockUntilWaitable, the exec_unix.go implementation variant for wait() could call syscall.Wait4 with syscall.WNOHANG, but blockUntilWaitable itself ensures that this is pointless (and the goal of this particular wait is to wait for exit anyway).

Java-like stepping out of a bash function when tracing it

While tracing a function in bash, I can return non-zero value (say,1) from by DEBUG trap handler to skip the execution of the next line.
Also, I can return the value 2 to execute a return statement to return out of the function without executing the rest of the function body
However, I would like to be able to step out of the current function, not by `return'ing, but by executing the remainder of the function body in just a single shot (instead of executing it line-by-line till the end of its body).
Is this possible?
Tedious sure, but it seems this can be done with the existing callstack information provided by Bash.
Here's how.
Keep executing your DEBUG trap handler till you reach the next callstack frame, F2, sitting right under the current one, F1, and stop on a line number that is greater than or equal to the BASH_LINENO saved in F2. The '... or equal to' check is required to address recursive calls.

Resources