Fixing multiple issues in "profctl" program
(related to program termination, and other):
Detailed list of changes:
1) profiling data pipe (`pipe_fd`) is opened in non-blocking mode (to
avoid blocking until external process starts) and made non-blocking for
reading;
2) start using raw file descriptor (`pipe_fd`) instead of libc file
(`pipef`) for reading end of data pipe;
3) control socket renamed from `control_socket` to `control_fd` (this
might be non socket, but any file) and made non-blocking for reading;
4) libc file `ctrl_file_in` isn't used anymore for reading control
socket (raw file descriptor is used directly);
5) libc file (`data_file_out`) isn't used anymore for writing profiling
data (raw file descriptor is used directly);
6) global variable `global_stop` eliminated, instead pipe `stop_pipe` is
used for stopping parallel threads;
7) second pipe `chld_pipe` used to process SIGCHLD synchronously (in
main loop);
8) flags which shows that particular thread terminated not used anymore;
9) MAIN CHANGE: not using anymore c-library functions from reading data
from non-blocking pipes or sockets (`pipe_fd` and `control_fd`), using
read(2) syscall with select(2) -- this allows correctly terminate
threads which blocks on reading from pipe or socket;
10) when copying data from data pipe (`pipe_fd`) to socket
(`data_socket`), using splice(2) system call (linux specific) to avoid
unnecessary copying via userspace;
11) external process starts after all sockets opened, but not before (to
simplify error handling), also stdin/stdout not closed begore exec, but
replaced to "/dev/null", stderr is never closed to allow errors
reporting;
12) in main loop (in main() function) only three reasons to terminate
application exists:
* closing control file/socket/pipe;
* "exit" command sent in control pipe;
* external process termination.
If external process closes data pipe, if data copying thread fails, if
statistics thread fails -- none of this will terminate application, it
will wait until one of the three events listed above.
13) rewritten thread termination logic (now using just pthread_join() in
regular way);
14) rewritten code for extern program termination logic;
15) added -Wall and -Wextra CMakeLists.txt, fixed warnings;
16) added "--help" option to command line arguments;
17) fixed issue with wrong terminal settings on exit;
18) commented out code which closes stdin/stdout/stderr and calls
raise(SIGKILL) -- I not understood why this need, looks like some dirty
trick to avoid other bugs.
profctl.c file modified (see below)
Detailed list of changes:
1) code changed accordig code review comments;
2) reporting of dotnet-launcher exit code via socket;
3) fixed bug (SEGFAULT on exit when no stat thread started);
4) fixed few issues with non-blocking IO;
5) added FD_CLOEXEC for most files;
6) removed terminal-controlling functions (not needed);
7) removed close_files_and_sockets() function (not needed, because of using FD_CLOSEXEC option);
8) watching for helper process termination and log errors;
9) fixed issues with unexpected helper process termination;
10) fixed bugs/warnings.
profctl.c: added more comments, no program's logic changed.
profctl.c: redirect stderr of child processes to the log.
profctl.c: fixed bug -- 100% cpu load in data copying thread.
profctl.c: increase pipe size for helper process to avoid unwanted delays
profctl.c: setting pipe size for heaptrack_interpret
Increasing pipe buffer size at OS level might avoid program stops in
cases, when heaptrack_interpret works too slow.
Previously logger thread might hang if child process doesn't close other
end of the pipe.