Is there any library which's got some function the allows one to monitor an external process for events by its pid_t
? I mean, monitoring whether an external process has exited, or whether it has created one or more child processes (with fork
), or whether it has become another executable image (via an exec
or posix_spawn
function family call) or whether a Unix signal was delivered to it.
EDIT
I need something that does not interfere with the execution of the program that is being monitored. So, I'm not supposed to use ptrace
, since it stops the process which is being monitored when it emits some signal and it's necessary to resume the process whenever this happens.
There are few tools available which can collect information about a process while it is running.
I suggest you to use perf and systemTap.
https://perf.wiki.kernel.org/index.php/Main_Page
http://sourceware.org/systemtap/SystemTap_Beginners_Guide/index.html
If you can run as root, then you can use the netlink interface proc events:
http://bewareofgeek.livejournal.com/2945.html
I just compiled it cleanly on fedora 17 x86_64 and it gives me this:
You'll need to filter for the specific pids which are of interest to you, but you can easily do that in the switch statement on line 107.
For purposes of preservation:
(gcc -o proc proc.c)
And some info on netlink:
excerpt: http://www.linuxjournal.com/article/7356
There's also this interesting announcement for nltrace made recently that you might find interesting as well! http://lists.infradead.org/pipermail/libnl/2013-April/000993.html
Use "pidof" system command from the procps library . Very simple and easy to use. If it returns something then the process is running or vice versa.
Run the target binary using a preload library that catches
fork()
. As long as all child processes also use the preload library, you'll see all local child processes, no matter how executed.Here is an example implementation.
First, the
forkmonitor.h
header file. It defines the messages passed from the preload library, to the monitoring process:The
FORKMONITOR_SOCKET
environment variable (named by theFORKMONITOR_ENVNAME
macro above) specifies the Unix domain datagram socket addess to the monitoring process. If not defined or empty, no monitoring messages are sent.Here is the library itself,
libforkmonitor.c
. Note that I simplified the code quite a bit, leaving out multithreaded initialization (since it's rare for a library to call any of the intercepted functions, and even rarer to do it from multiple threads). It would be better to use atomic built-ins (__sync_bool_compare_and_swap()) to update the function pointer, and atomic getter (__sync_fetch_and_or(,0)) to retrieve the function pointer, to avoid any issues with wonky libraries. (This is quite safe for multithreaded programs, as the pointers will only be modified prior tomain()
is executed.)The
libforkmonitor_init()
function is called automatically by the runtime linker before the processmain()
is called, andlibforkmonitor_done()
is called when the process returns frommain()
or callsexit()
.The
libforkmonitor_init()
opens an Unix domain datagram socket to the monitoring process, and sends its credentials and the path to the current executable. Every child process (as long as the preload library is still loaded) executes this after they're loaded, so there is no need to catchexec*()
orposix_spawn*()
or 'popen()` etc. functions at all.The C library functions
fork()
andvfork()
are intercepted. These interceptions are needed to catch the cases where the original program forks to create slave processes without executing any other binary. (At least GNU C library usesfork()
internally, so these will catchpopen()
,posix_spawn()
, etc. too.)Additionally, C library functions
_exit()
,_Exit()
, andabort()
are intercepted too. I added these because some binaries, especially Dash, like to use_exit()
, and I thought it would be nice to catch all forms of normal exits. (Death due to signals is not detected, however; and if a binary executes another binary, you'll only get the new EXEC message. Note the process and parent process ID's.)Here is a simple monitoring program,
forkmonitor.c
:It takes a single command-line parameter, the Unix domain socket address. It should be an absolute file system path.
You can stop the monitoring program via
INT
(Ctrl+C),HUP
,QUIT
, andTERM
signals.Compile the library using
and the monitor program using
In one terminal window, start the forkmonitor first:
In another terminal window, in the same directory, run the monitored command, automatically preloading the
libforkmonitor.so
library and specifying the socket for the monitor:Note that because this uses the
LD_PRELOAD
andFORKMONITOR_SOCKET
environment variables, child processes are ignored if their parent modifies the environment (removing the two environment variables), and when executingsetuid
orsetgid
binaries. This limitation can be avoided by eliminating the environment variables, and hardcoding them.The run-time linker will not preload libraries for
setuid
orsetgid
binaries, unless the library is in one of the standard library directories, and also markedsetgid
.Adding the library name to
/etc/ld.so.preload
will preload the library for all binaries, but you probably should add a mechanism intolibforkmonitor_init()
which limits the monitoring to desired binaries and/or a specified real user (as effective user changes when running a setuid binary).For example, when I run
the monitoring output is (anonymized):
This is a very lightweight process tree monitoring solution. Other than process startup, exit, and calling one of the intercepted functions (
fork()
,vfork()
,_exit()
,_Exit()
,abort()
), program execution will not be affected at all. Because the library is so lightweight, even those affected will only be affected by a very, very small amount; probably not enough to measure reliably.It is obviously possible to intercept other functions, and/or use two-way communication, "pausing" the execution of the intercepted function until the monitoring application responds.
There are some pitfalls overall, especially related to setuid/setgid processes, and processes that generate a new environment (omitting the
LD_PRELOAD
andFORKMONITOR_SOCKET
environment variables), but those can be worked around if superuser privileges are available.Hope you find this informative. Questions?