How do I prevent valgrind from creating extra log files when using popen? - valgrind

valgrind-3.15.0
I have a weird issue with valgrind when I use switches --trace-children, --trace-children-skip and --log-file along with popen().
My code:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *fp = NULL;
fp = popen("ls -l", "r");
pclose(fp);
fp = popen("ls -l", "r");
pclose(fp);
fp = popen("ls -l", "r");
pclose(fp);
fp = popen("ls -l", "r");
pclose(fp);
fp = popen("ls -l", "r");
pclose(fp);
return EXIT_SUCCESS;
}
Command 1: valgrind --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=*/sh,*/ls ./test
When I run this command I get only one process output in STDOUT. That's what I expect because I'm specifying with the --trace-children-skip to ignore what I'm doing with popen().
Command 2: valgrind --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=*/sh,*/ls --log-file=logs/%p ./test
When I run this command I get 6 log files. One for the main process and one for each of the popen() calls. valgrind reports the command as ./test. This is not what I'd expect. I'd expect the same as above, only one process log.
Running without --trace-children-skip I'd get 11 files; one for the main process and two for each of the popen() calls (sh and ls as the commands). This is what I'd expect since I'm not skipping anything and popen() calls sh which then calls ls.
I'm not sure what the deal is here. --trace-children-skip with --log-file is working in that it's not showing the sh and ls logs, but it's still creating a process for each popen() call which doesn't happen if I don't use --log-file. Am I missing something?

Related

Prevent CUDA-enabled MPI from checking for CUDA devices

The OpenMPI 4.0.5 on our cluster is built with CUDA support, but I want to benchmark pnetcdf without needing CUDA for that. Since I want to do a number of test runs that I can start on like 1/4th of a node and my tests won't make use of the GPUs I wanted to ask if there is a way to suppress the MPI check for CUDA devices. Because when I simply obtain a SLURM allocation without GPUs, I get lots of errors from that alone.
These errors come from hwloc, and can be suppressed with HWLOC_HIDE_ERRORS=1 but I'd like to know if there is a more specific method.
Steps to reproduce:
frontend$ salloc -n 16 -t 8:00:00 -A k20200
node$ exec bash -l
node$ module load gcc openmpi
node$ mpicc -o /tmp/hello ~/usr/src/helloworld_mpi.c
node$ srun -n 1 /tmp/hello
CUDA: Failed to get number of devices with cudaGetDeviceCount(): no CUDA-capable device is detected
Hello world!, I'm rank 0 of 1!
node$ HWLOC_HIDE_ERRORS=1 srun -n 1 /tmp/hello
Hello world!, I'm rank 0 of 1!
node$ logout
The example code used above is the following but any program without CUDA use is equally useful in this exercise
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#define xmpi(rc) \
do { \
int err = (rc); \
if (err != MPI_SUCCESS) { \
char msg[MPI_MAX_ERROR_STRING + 1]; \
int msg_len; \
\
if (MPI_Error_string(err, msg, &msg_len) \
== MPI_SUCCESS){ \
msg[msg_len] = '\0'; \
\
fprintf(stderr, \
"Problem in MPI call: %d = %s\n", \
err, msg); \
MPI_Abort(MPI_COMM_WORLD, 1); \
} \
} \
} while (0)
int
main(int argc, char *argv[])
{
xmpi(MPI_Init(&argc, &argv));
int rank, size;
xmpi(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
xmpi(MPI_Comm_size(MPI_COMM_WORLD, &size));
printf("Hello world!, I'm rank %d of %d!\n", rank, size);
xmpi(MPI_Finalize());
return EXIT_SUCCESS;
}

Hello world llvm-lit with cfg file

I'm trying to run a simple test with llvm-lit. I have a dedicated directory:
llvm-lit-dir
+---lit.cfg
+---llvm_lit_example.c
The cfg file is from llvm-3.8.0/utils/lit/lit/ExampleTests.ObjDir.
Here it is:
$ cat lit.cfg
config.example_obj_root = os.path.dirname(__file__)
lit.load_config(config, os.path.join(config.test_source_root,'lit.cfg'))
Here is the example I'm trying to check:
$ cat llvm_lit_example.c
// RUN: %clang -o %t0 %s
// RUN: %t0 | grep "YES"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int i=rand()%4;
char s1[5]={'0','1','2','3', 0 };
char s2[5]={'0','1','2','3', 0 };
s1[i]='6';
if (strcmp(s1,s2) == 0) printf("NO \n");
if (strcmp(s1,s2) != 0) printf("YES\n");
}
I've tried several options but none seem to work:
$ llvm-lit llvm-lit-dir/llvm_lit_example.c
llvm-lit: TestingConfig.py:114: fatal: unable to parse config file '/home//llvm-lit-dir/lit.site.cfg', traceback: Traceback (most recent call last):
File "/home/llvm-3.8.0/llvm/utils/lit/lit/TestingConfig.py", line 101, in load_from_path
exec(compile(data, path, 'exec'), cfg_globals, None)
File "/home/llvm-lit-dir/lit.site.cfg", line 14, in <module>
lit.load_config(config, os.path.join(config.test_source_root,'lit.cfg'))
NameError: name 'lit' is not defined
What am I doing wrong? Thanks!
The following is the minimalistic "hello world" example which is now working for me:
config file: lit.cfg
import lit.formats
config.name = "LIT hello world"
config.test_format = lit.formats.ShTest("0")
test file: tests/test
; RUN: echo "Foo" | FileCheck %s
; CHECK: Foo
run it with
lit -v tests/test
To make the test fail, change it to echo "Bar".
Two additional comments:
1) Installing lit is easy:
pip3 install lit
To install FileCheck I had to download LLVM source code (LLVM Download page) and build the FileCheck target using CMake.
2) config.test_format = lit.formats.ShTest("0") is important because otherwise lit fails with the following error:
AttributeError: 'NoneType' object has no attribute 'execute'
It looks like ShTest is a default format, but a user still has to activate it manually.
This config is a python source. lit there is clearly undefined. Try importing something related to lit, like from lit.llvm import llvm_config. Take a look at test/lit.cfg.py in LLVM source.

How to execute a GDB command from a string variable?

Say the debugged process has a string variable as follows:
char* cmd_str = "set confirm on";
How to execute the command from cmd_str in GDB?
(gdb) $cmd = cmd_str
(gdb) ???
You can use gdb's eval command, which runs printf on its arguments and then evaluates the result as a command.
(gdb) list
1 #include <stdlib.h>
2 main()
3 {
4 char *a = "set confirm off";
5
6 pause();
7 }
(gdb) break 6
Breakpoint 1 at 0x400540: file cmdtest.c, line 6.
(gdb) run
Starting program: ./cmdtest
Breakpoint 1, main () at cmd.c:6
6 pause();
(gdb) show confirm
Whether to confirm potentially dangerous operations is on.
(gdb) printf "%s", a
set confirm off(gdb)
(gdb) eval "%s", a
(gdb) show confirm
Whether to confirm potentially dangerous operations is off.

Getting CPU info from Process ID

If anyone could please help me out, that would be great :)
This seems to be a tough one. Starting from the process ID, I need to be able to grab:
How much CPU the process is taking up in %
How long the process has been using the CPU
This needs to be written in Cocoa/ Objective-C or C. It also needs to work on Tiger through Snow Leopard.
Thanks!
A crude way would be to spawn of a popen command and grab some output from ps.
Ie like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void get_process_info(int pid) {
char ps_cmd[256];
sprintf(ps_cmd, "ps -O %%cpu -p %d", pid); // see man page for ps
FILE *fp = popen(ps_cmd, "r");
if (fp) {
char line[4096];
while (line == fgets(line, 4096, fp)) {
if (atoi(line) == pid) {
char dummy[256];
char cpu[256];
char time[256];
// PID %CPU TT STAT TIME COMMAND
// 32324 0,0 s001 S+ 0:00.00 bc
sscanf(line, "%s %s %s %s %s", dummy, cpu, dummy, dummy, time);
printf("%s %s\n", cpu, time); // you will need to parse these strings
pclose(fp);
return;
}
}
pclose(fp);
}
}
int main() {
get_process_info(32324);
return 0;
}

Calling fgets() on popen() of 'ssh' is flushing the beginning of stdin of the calling process (ptty issue)

I have now whittled this down to a minimal test case. Thus far I have been able to determine that this is an issue related to pseudo-terminals which come about with the pipe of ssh. Adding the '-t -t' to the ssh call improved things, in that now, it takes a second call to fgets() to cause the issue. I suspect that the stderr output of the ssh command somehow works into the issue, for now I have redirected stderr to stdout in the ssh code to execute. I do wonder if the "tcgetattr: Invalid argument" error is part of the problem, but am not sure how to get rid of that. It seems to come from the -t -t being present. I believe the -t -t is moving in the right direction, but I have to set up the pseudo terminal for stderr somehow and perhaps the test will work properly?
The Makefile:
test:
gcc -g -DBUILD_MACHINE='"$(shell hostname)"' -c -o test.o test.c
gcc -g -o test test.o
.PHONY: clean
clean:
rm -rf test.o test
The test.c source file:
#include <unistd.h>
#include <string.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
const unsigned int bufSize = 32;
char buf1[bufSize];
char buf2[bufSize];
int ssh = argv[1][0] == 'y';
const char *cmd = ssh ? "ssh -t -t " BUILD_MACHINE " \"ls\" 2>&1" : "ls";
FILE *fPtr = popen(cmd, "r");
if (fPtr == NULL) {
fprintf(stderr,"Unable to spawn command.\n");
perror("popen(3)");
exit(1);
}
printf("Command: %s\n", cmd);
if (feof(fPtr) == 0 && fgets(buf2, bufSize, fPtr) != NULL) {
printf("First result: %s\n", buf2);
if (feof(fPtr) == 0 && fgets(buf2, bufSize, fPtr) != NULL) {
printf("Second result: %s\n", buf2);
int nRead = read(fileno(stdin), buf1, bufSize);
if (nRead == 0) {
printf("???? popen() of ssh consumed the beginning of stdin ????\n");
} else if (nRead > 0) {
if (strncmp("The quick brown fox jumped", buf1, 26) != 0) {
printf("??? Failed ???\n");
} else {
printf("!!!!!!! Without ssh popen() did not consume stdin !!!!!!!\n");
}
}
}
}
}
This shows it running the passing way:
> echo "The quick brown fox jumped" | ./test n
Command: ls
First result: ARCH.linux_26_i86
Second result: Makefile
!!!!!!! Without ssh popen() did not consume stdin !!!!!!!
This shows it running the failing way:
> echo "The quick brown fox jumped" | ./test y
Command: ssh -t -t hostname "ls" 2>&1
First result: tcgetattr: Invalid argument
Second result: %backup%~ gmon.out
???? popen() of ssh consumed the beginning of stdin ????
Okay, I have got this working finally. The secret was to supply /dev/null as the input to my ssh command as follows from the test case above:
const char *cmd
= ssh ? "ssh -t -t " BUILD_MACHINE " \"ls\" 2>&1 < /dev/null" : "ls";
However, while the code works correctly, I get a nasty message which apparently I can ignore for my purposes (although I'd like to make the message go away):
tcgetattr: Inappropriate ioctl for device