I have to write console app which starts another process (GUI). Then with other app or option of the same I have to be able to stop the child process. In addition, if the child process is closed from GUI, I have to be informed to do final tasks (same if killed).
I suppose it is good to keep first (parent) app running while child (GUI) is working and continue with final tasks. For example in .Net this is made with Process.WaitForExit() after Process.Start().
Read wait(2) and exit(2) system calls manpages. wait(2) stops the calling process until some of it's children has exit(2) and exit(2) just do the reciprocal, exits the program and lets the kernel inform its parent process of that, passing it the exit code supplied.
Related
I am dealing with an odd problem which I couldn't find the answer to online, nor through a lot of trial and error.
In a multi-multi process cluster, forked worker processes can run arbitrarily long commands, but the parent process listens for keepalive messages sent by workers, and kills workers that are stuck for longer than X seconds.
Worker processes can asynchronously communicate with the rest of the world (using http, or process.send ipc communication), but on exit, I'd like to be able to communicate some things (typically, queued logs or error details).
Most online documentation for process.on('exit', handler) indicates usage of console.log, however it seems like forked processes don't inherit a normal stdout, and the console.log isn't a direct tty, it's a stream (the ipc stream, I presume?).
Because of this, the process exit handler doesn't let me use console.log to log extra lines (or if it does, I'm not sure where these lines end up)
I tried various combinations of fork options (silent/not silent, non-default stdio options like inherit), using fs.write to write to tty or a real file, using process.send, or but in no case, was I able to get the on-exit handler to log anywhere visible.
How can I get the forked process to successfully log on exit?
small additional points - all this testing is on unix-like systems (macos , amazon linux...) and both parent and child processes are fired with --sigint-trace so that we can get at least the top 10 stack frames of the interrupted process on exit. These frames do make it out to the terminal successfully
This was a bit of a misunderstanding about how SIGINT is handled, and I believe that it's impossible to accomplish what I want here, but I'd love to hear if someone else found a solution.
Node has its own SIGINT handler which is "more powerful" than custom SIGINT handlers - typically it interrupts infinite loops, which is extremely useful in the case where code is blocked by long-running operations.
Node allows one-upping its own SIGINT debugging capabilities by attaching a --trace-sigint flag which captures the last frames of execution.
If I understood this correctly, there are 4 cases with different behavior
No custom handler, event loop blocked
process is terminated without any further code execution. (and --trace-sigint can give a few stack traces)
No custom handler, event loop not blocked
normal exit flow, process.on('exit') event fires.
Custom handler, event loop blocked
nothing happens until event loop unblocks (if it does), then normal exit flow
Custom handler, event loop not blocked
normal exit flow.
This happens regardless of the way the process is started, and it's not a problem about pipes or exit events - in the case where the event loop is blocked and the native signal handler is in place, the process terminates without any further execution.
It would seem like there is no way to both get a forced process exit during a blocked event loop, AND still get node code to run on the same process after the native interruption to recover more information.
Given this, I believe the best way to recover information from the stuck process is to stream data out of it before it freezes (sounds obvious, but brings a lot of extra considerations in production environments).
I was playing on my virtual machine with some exploit learning tricks when i came across this script that was printing to 2 lines and then exit to prompt, and after 10 seconds it printed in my prompt like this :
[!] Wait for the "Done" message (even if you'll get the prompt back).
user#ubuntu:~/tests$ [+] Done! Now run ./exp
How is this possible ? It is clone involved or something like that ?
The program informs you that you should wait for the "Done" message even if you get the prompt back earlier.
This is because some other process is running, detached, in the background.
The process you started has finished, which is why you are getting the prompt back. But it spawned another (background) process, e.g. via fork() or some other mechanic. By the time you get your prompt back, that other process is still running, and you are told to wait for it to finish.
When it does, it prints "Done" to the standard output (stdout) it inherited from its parent -- which is (by default) the same terminal you used to start the initial process.
Not the smoothest design -- the main process could wait for the spawned process to finish before giving you that prompt back, since it is apparently important that other process finishes before you carry on. Perhaps the author didn't know how to do that. ;-)
The process, responsible for printing the messages are running in background (background process).
In general, running a process in background means detaching only the stdin, the stdout and stderr are still linked to the actual parent shell, so all the outputs are still visible on the terminal.
My question is a bit theoretical.
Lets say I have a process with PID 10, in order to terminate it I can use both exit and kill.
exit command bring the process to Zombie state and later the process is beeing removed thru the release_task() func.
But what happens when kill is called on a process ? Does kill call exit ? Do the process become zombie?
I really dont understand how killworks behind the scenes and which kernel function do the job
If it changes anything - im working (actually studying) on a v2.4.18 machine
Thank you very much
I am trying to write a Node.js program to execute and monitor javascript programs. I am looking for a way to find out whether the monitored program is still "running" i.e. doing anything useful.
In my current approach, when receiving code to test, I start a new child process and hand the code to it. The child process instruments the code creates a Sandbox using Contextify and executes the code using this sandbox.
After the sandbox.run(code) call returned I know that the blocking part of the code finished and can show that in the UI. However, I don't now whether the code registered any timers using setTimeouts or created any other event sources that would cause parts of the code to be exited later. So I don't know whether it's really "finished" yet.
Is there a way in Node.js to check whether there are still events on the event loop to be handled (or even better, how many are left)?
I found this other question, but it only talks about how to monitor the event loop to find out whether the performance of node is still fine. But I'm not interested in the performance (I don't care if the executing code is blocking for 10s or only doing something for 1ms every 2 minutes) and I don't want to use outside tools but find out about the state of the event loop from inside node itself. Is that possible?
I solved my problem in a way, although I didn't find a general answer to the question.
The idea here is that the process will exit by itself if it has executed all the code it was started with and no EventEmitters are registered anymore. This was basically what I wanted, since I wanted to be notified when the process was "done" and now I could just listen to the "exit" event of the child_process.
But my process that executed the code didn't exit by itself. This had two reasons:
I used a timer to regularly send the data gathered about the execution to the parent process. If such a timer is registered the process won't exit. You could unref the timer but I was afraid that would lead to data loss since the process could quit before the last bit of data was sent out (since it wouldn't wait for the timer to execute). So I changed my code to only schedule a timer if there was data to be sent out instead of regularly checking for data to be sent.
I used fork to create the child process. This also creates a communication channel between the parent and child process and since I needed to send the code to execute to the child_process I registered the child process for messages received from the parent using process.on("message", callback). However, now we have another EventEmitter registered which prevents the process from quitting. Luckily, I realized that I only needed one message from the parent process and no further messages so I could remove the event emitter after receiving that message. So instead of process.on() I used process.once() which will execute the callback only once and automatically remove the event emitter after that. Exactly what I wanted. Alternatively you could use process.removeListener().
Now I just wait for the child_process to exit and thus know that everything is finished and can notify the client.
So the solution here is to make sure none of your own EventEmitters keep the process alive and then just wait for it to exit.
I have a shared object that I have written which I link to an Linux executable (say a game for example). Now when the program finishes (game over!), what kind of signal handler should I have in my shared object that I created in order to perform some cleanup activities?
Please remember that I DO NOT have control over the Linux executable, it is a game that I simply download from the Internet and run it by linking it to my shared object. When the game finishes, I want to be able to catch that event and do some cleanup activities.
Have I made my question clear? Any ideas?
Thanks,
Krishna
if you run the game as a child process, you'll get SIGCHLD (17) when the other process ends.
If the main application uses the standard C library, then you can make use of the atexit(3) function to register a function to be called when the application exits.
There are a number of cases where the function will not be called though (abnormal termination through signals, a call to _exit(2), etc), so check the man page to see if all your use cases are covered.
In general, you can't do this from within the process. (Software can't have dying wishes.)
However, you could run the existing game process inside a wrapper script or something that runs another program after the game finishes:
#!/bin/sh
run_game
perform_cleanup_activity