My process launches a process - let it be a shell in this example, but it's applicable to any process really. I need to get notified when the shell creates new processes and to obtain their PIDs.
I can take a snapshot of the whole process tree at any given time (well, pstree can), but how do I monitor creation of new processes by a process with a given PID?
So far I've found several ways to do so at How to monitor an external process for events by its PID in C? none of which really solve my problem:
Monitoring NetLink proc interfaces. Problem: requires root permissions which I do not have.
Custom library overriding the syscalls loaded into the shell process by LD_PRELOAD. Problem: it will be inherited by the children of the shell as well, and I do not want that - I only want to monitor the shell.
ptrace()ing the shell. Problem: flags that notify the parent (i.e. my process) about creating new processes, i.e. PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK and PTRACE_O_TRACECLONE propagate ptrace()ing to child processes, and I only want to monitor the shell.
Making the shell cooperate. Problem: In BASH command callbacks (as used in undistract-me) are very hacky. I'd also prefer to avoid shell-specific code.
I feel like I'm missing something simple here. I feel like I could make one of the above solutions work with more hacks, but... surely I don't have to resort to the big guns like LD_PRELOAD and ptrace() for such a simple task, do I?
JFYI I'm coding this in Vala, but C snippets are welcome too.
No generic solution has been found so far so I had to resort to making the shell cooperate:
ZSH has pre-exec hook documented in
http://zsh.sourceforge.net/Doc/Release/Functions.html
KSH has a
debug hook documented in http://www.manpagez.com/man/1/ksh/
a hack that adds pre-exec to BASH can be found in
https://github.com/jml/undistract-me
I simply write callback commands into the relevant environment variables depending on the shell.
Related
I've been asked to create a dbus interface to a program that uses SocketCAN to communicate to a set of control units on a car (that's just background info and not relevant to the question). The original concept was to use a listener interface that spawned a new "node" for each control unit being interrogated in the car. This would lead to something like the following objects on the com.acme.myservice bus:
/com/acme/listener
/com/acme/node1
/com/acme/node2
...
/com/acme/nodeN
The idea is to take over the code from a C program that already communicates from the command line with a single ECU. That code depends on fork()ing in order to run parts of the communication cyclically and other parts in parallel for timing reasons.
I had planned on using the GDBusObjectManager model using new code for the listener and reusing the fork()ing code for each node instance. Unfortunately I ran into trouble because I still need to process DBus messages and relay the information to the (now forked) children and that's not supported:
On UNIX, the GLib mainloop is incompatible with fork(). Any program using the mainloop must either exec() or exit() from the child without returning to the mainloop.
I could restructure the forking code so that it executes in a single process in between iterations of the main loop instead of using g_main_loop_run but this will probably cause too much latency if there's a significant amount of data and multiple nodes running.
What's the best way around this? Is it possible to somehow handle these parallel items with a built-in glib mechanism or is there a way around the mainloop/forking issue? Is the only solution to use a different IPC mechanism between a single process using DBus and forked children doing the actual work? (This would probably be as much code as needed for the gdbus interface so it makes it sort of redundant)
Sorry if the title doesn't make any sense, it's all I could think to call it.
I'm learning about how processes work in *nix systems (Linux in my case) and I know a little bit but I want to figure out how to do this, if possible, and I can't find anything about probably since I don't know what to call it.
The best way for me to explain this would be to give an example:
Say I have a music player which operates in the terminal, lets call it "musicplayer".
I want to play a sound file, so I would execute this command:
musicplayer play "/path/to/music.mp3"
Then this runs in the background and I'm back at my prompt in the terminal, I can just completely exit from the terminal and hear the music in the background etc...
Say halfway through the song I want to pause it:
musicplayer pause
Some how the music is paused.
How would this work? (I mean in terms of the process, the music is only an example, the question is not about music).
In my mind this is what's happening: [fork and play music] -> [tell the fork to pause].
I'm not very knowledgeable on the subject of processes yet so any help/explanation of this is highly appreciated.
I don't need code examples necessarily, just logically how this would work but if you wish to give examples you could give them in C.
Thanks in advance for any explanation.
You need to understand that forked processes do not share (implicitly) any data; conceptually parent and child processes have each their own address space and have their own copy of the data (using lazy copy on write techniques). See fork(2)
Hence, you need to make them explicitly communicate and synchronize with pipe(7)-s, fifo(7)-s, socket(7)-s, shared memory shm_overview(7) with semaphores sem_overview(7), eventfd(2) or whatever other means Linux provides you.
So read Advanced Linux Programming and learn about the syscalls(2) available on Linux to do Inter Process Communication. Don't forget to handle syscall failure.
For your music play command you would set up IPC and fork (see also daemon(3) to fork a daemon in the background).
For your music pause you would communicate with the other process. (you might perhaps consider stopping the process with the SIGSTOP signal(7) using kill(2)...)
You need to build in your head an image of all the IPC facilities available to chose the ones relevant for your situation
BTW, several command-line music players exist on Linux as free software. You could study their source code and/or strace(1) their execution.
I'd like to add one thing to Basiles answer: this is a very common problem so almost certainly you don't have to handle the details (that can be very complex) yourself. Good application frameworks will provide a solution for you so you can concentrate on making the application great.
As an example, take a look at GLibs GApplication: It handles application uniqueness so the first instance will keep running and any subsequent app invocations will just send a D-Bus message to the original instance and exit. The GApplication object in the original instance will emit a signal that tells your app e.g.that a musicplayer instance was started on command line and and the argument was "pause".
I am working on a school project, and though it's not required, I want to implement this functionality. With that said, I can't share code, but I think it's irrelevant in this case.
When using fork(), my understanding is that the child process created inherits stdin and stdout, as the child inherits all the file streams from the parent.
My shell requires background capability, and while it technically already has that, if the "background" program runs, it still receives all the data from stdin and continues output to the screen which is just a jumbled mess. For the record, my instructor's compiled sample shell does the same thing, but I don't want that to happen!
I'm pretty certain I should be using a combination of pipe(), fork(), and dup2(), but I can't put it all together. I understand fork, but I don't understand how pipe or dup2 works and how I should implement it in the shell. I'm thinking something along these lines:
thePipe[2] = pipe();
pid = fork();
close stdin/out on child somehow if backgrounded
But I don't understand the functionality of pipe() or dup2() so I'm stuck.
Thanks!
You don't want pipes here. Processes run in an interactive shell should share their standard file descriptors with the shell — doing otherwise would break a lot more things (including the child processes' ability to determine they're running interactively, and to interact with the tty to handle things like window size changes). It'd also seriously complicate pipelines. Don't do it.
The missing piece here is process groups, which are described in the "General Terminal Interface" section of the Open Group UNIX specs. In brief, the kernel can be made to explicitly recognize a "foreground process group" for the terminal. If a process that isn't in this group tries to read from or write to the terminal, it is automatically stopped.
A brief walkthrough of what is necessary to make a properly functioning shell is available as part of the GNU libc manual, under "Implementing a Job Control Shell". Try following their instructions and see how that goes.
I would like to create a new process of an exe from within the code itself, so that I can have two parallel processes.
But, I would like to them to be separate processes and not parent-child.
Is there a way to do this in C (Windows)?
In Windows, processes don't have parents. Some tools read the InheritedFromUniqueProcessId value, but this does not tell you which process started your process. It only tells you where handles and other attributes were inherited from. In practice however, this value is usually set to the ID of the process that started the child process.
On Vista and above, you can change the InheritedFromUniqueProcessId value by calling CreateProcess with the STARTUPINFOEX structure filled in appropriately: create an attribute list with InitializeProcThreadAttributeList, and add a
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS attribute with UpdateProcThreadAttribute.
On XP, there is no official way of doing this. You can try to use NtCreateProcess or RtlCreateUserProcess, but these don't set up the Win32 subsystem properly so your program might not run.
An ugly way I've done it in the past is to launch a child process, which then launches a second child process, and then the first child exits. This causes the second child to lose any association with the original parent.
I'm sure I later found a better way to do this, but I've gone looking around and can't find anything at the moment.
The "easy" way is to use an intermediate command, see KB here:
http://support.microsoft.com/kb/315939
Another way to have independent processes is to ensure to do not inherit handles to ensure that the 2nd process, and creating a new process group. See Creating independent process!
Most likely forking a new process doesn't exist in windows rather you could use CreateProcess function to do that which is much easier and better option for windows.
If the fork and exec patter is used just to run a program without freeze the current program, what's the advantage, for example, over using this single line:
system("program &"); // run in background, don't freeze
The system function creates a new shell instance for running the program, which is why you can run it in the background. The main difference from fork/exec is that using system like this actually creates two processes, the shell and the program, and that you can't communicate directly with the new program via anonymous pipes.
fork+exec is much more lightweight than system(). The later will create a process for the shell, the shell will parse the command line given and invoke the required executables. This means more memory, more execution time, etc. Obviously, if the program will run in background, these extra resources will be consumed only temporarily, but depending on how frequently you use it, the difference will be quite noticeable.
The man page for system clearly says that system executes the command by "calling /bin/sh -c command", which means system creates at least two processes: /bin/sh and then the program (the shell startup files may spawn much more than one process)
This can cause a few problems:
portability (what if a system doesn't have access to /bin/sh, or does not use & to run a process in the background?)
error handling (you can't know if the process exited with an error)
talking with the process (you can't send anything to the process, or get anything out of it)
performance, etc
The proper way to do this is fork+exec, which creates exactly one process. It gives you better control over the performance and resource consumption, and it's much easier to modify to do simple, important things (like error handling).