I have a binary called "ifmFuseHandler" which is invoked by a shell-script something like this:
su - $USER -c "cd $DIR_INDEX;valgrind --leak-check=full ifmFuseHandler $IFM_SINGLE_THREAD -o allow_other $IFM_MOUNT"
But the problem is, i can see the valgrind logs only once, when the control hits this line of shell, and post that even though the ifmFuseHandler is up and running, valgrind does not provide any profiling info.
So, as you can see below, but no further logging:
insite1#POC-Messaging1:/opt/insiteone/log> ps -ef | grep ifmFuseHandler
insite1 622 1 0 04:19 ? 00:00:02 valgrind --leak-check=full ifmFuseHandler -o allow_other /opt/insiteone/fuse-mount
insite1 3225 26014 0 04:32 pts/2 00:00:00 grep ifmFuseHandler
You need to adjust your shell-script to explicitly log the output of valgrind to a file as described here.
If your program is invoked multiple times, try using a filename with the PID, as described in the usage of --log-file=<filename> here.
Just make sure your output file is in an easily readable location.
Related
I've got a program written in C++ which has a function that looks similar to this:
std::string cmd = "curl -s http://x.x.x.x/latest/meta-data/public-hostname";
std::vector<std::string> output;
runCmd(cmd, output);
If the curl command fails the program silently ignores it. I need to be able to examine what's happening when the program gets to this point: I'd like to look at the output generated by curl, including error message and return code.
How do I do this with gdb? Please walk me through the steps of running the program with gdb so I can see what's happening with curl. It's a fairly large program. I am only interested in this particular function call, I want to ignore everything else up to that point.
i should note that I don't have the environment to compile the code. All I've got is the binary.
Not sure gdb will help you much as you spawn a sub process.
I would suggest changing the code to
std::string cmd = "curl -s http://x.x.x.x/latest/meta-data/public-hostname 2>/tmp/error | tee /tmp/output";
so that /tmp/erro and /tmp/output gives you what happened;
EDIT:
as compilation os not possible, you may use this trick:
create a script named curl containing:
#!/bin/bash
/usr/bin/curl $# 2>/tmp/error | tee /tmp/output
(don't forget to change permission to +x)
then, when executing your program just do:
PATH=.:$PATH ./yout_binary
assuming your script is in .
then the program will use your 'fake' curl
I would use strace for this task, rather then gdb:
strace -f -s 1024 -o log ./program
Here -f mean to trace child processes as well. You need it because this line of code runCmd(cmd, output); most likely does fork() to run child process.
-s 1024 specifies maximum string size to print. By default it is 32 which is often too short.
Once you save the output to log file, you should easealy find something like curl -s in it. This is where the child process starts. You can see what it writes to stderr or stdout in lines like write(2, "... or write(1, ".... At the end of the process execution you will see it's exit code, for example 1 exit code:
exit_group(1) = ?
When I directly run a command in my Linux terminal, say "ls", the output is with color. However, when I run a C++ program which calls system("ls"), the output does not have color.
Is there way to get the latter way to also display colored output?
Thanks!
The answer for why there's no color lies here.
system() executes a command specified in command by calling /bin/sh -c
command, and returns after the command has been completed.
sh -c ignores aliases. Perhaps somewhere you have an alias where ls means ls --color=auto.
So for example, if I do sh -c 'ls', I will get no color.
Proof:
wow ♪[01:04 AM][vnbraun#chernobyl ~]$ which ls
alias ls='ls --color=auto'
/bin/ls
wow ♪[01:08 AM][vnbraun#chernobyl ~]$ sh -c 'which ls'
/bin/ls
Therefore, you can try doing system("ls --color=auto");.
You could run
system("/bin/ls --color=auto");
But I don't think you really should run ls from your C++ program. Perhaps you want to use -some combination of- readdir(3), stat(2), nftw(3), glob(3), wordexp(3) etc etc....
I don't think that forking a shell which then runs /bin/ls is useful from a C++ program. There are simpler ways to achieve your goal (which I cannot guess).
You probably should read Advanced Linux Programming
Try invoking ls --color=auto or ls --color=always to display ls with colors.
This is likely due to a bash configuration file somewhere in your system aliasing "ls" to "ls --color".
Using "ls --color" in your program should work.
I have a code executable as "demonstrate"> I want to have a neat memory profiling for thios executable. I have gone through the valgrind's massif tool and found out to be something which could fetch me results that I am looking for. Although there is a slight issues I am coming across.
My executable takes various arguments and w/o it it wont run e.g ./demonstrate -t 10 -p 1 -P 3
As soon as I run massif on the above statement it tells me
"Error allocating heap"
taskset -c 0-10 valgrind --tool=massif ./demonstrate -t 10 -p 1 -P 3
==4140== Massif, a heap profiler
==4140== Copyright (C) 2003-2010, and GNU GPL'd, by Nicholas Nethercote
==4140== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info
==4140== Command: ./demonstrate -t 10
==4140==
Error allocating heap
==4140==
Quite similar issue happened with mtrace. Included mcheck header and called mtrace and muntrace at the beginning and end and tried calling demonstrate
e.g
mtrace ./demonstrate -t 10 -p 1 -P 3 -f file.txt mALLOCoUT.TXT
Wrong number of arguments, run /usr/bin/mtrace --help for help. at /usr/bin/mtrace line 89.
Although when I run the application without the valgrind option the application runs fine:
./demonstrate -t 10 -p 1 -P 3
Opened 1
Opened 2
Opened 3
Allocated huge page size=1073741824
Pushed 262144 pages
Any suggestion on how to get any of these working with several command line arguments.
I have a process which suddenly hanged and is not giving any core dump and is also not killed.i can see it still running using the ps command.
how can i know which statement it is currently executing inside the code.
basically i want to know where exactly it got hanged.
language is c++ and platform is solaris unix.
demos.283> cat test3.cc
#include<stdio.h>
#include<unistd.h>
int main()
{
sleep(100);
return 0;
}
demos.284> CC test3.cc
demos.285> ./a.out &
[1] 2231
demos.286> ps -o "pid,wchan,comm"
PID WCHAN COMMAND
23420 fffffe86e9a5aff6 -tcsh
2345 - ps
2231 ffffffffb8ca3376 ./a.out
demos.290> ps
PID TTY TIME CMD
3823 pts/36 0:00 ps
23420 pts/36 0:00 tcsh
3822 pts/36 0:00 a.out
demos.291> pstack 3822
3822: ./a.out
fed1a215 nanosleep (80478c0, 80478c8)
080508ff main (1, 8047920, 8047928, fed93ec0) + f
0805085d _start (1, 8047a4c, 0, 8047a54, 8047a67, 8047c05) + 7d
demos.292>
You have several options: the easiest is to check the WCHAN wait channel that the process is sleeping on:
$ ps -o "pid,wchan,comm"
PID WCHAN COMMAND
2350 wait bash
20639 hrtime i3status
20640 poll_s dzen2
28821 - ps
This can give you a good indication of what the process is doing and is very easy to get.
You can use ktruss and ktrace or DTrace to trace your process. (Sorry, no Solaris here, so no examples.)
You can also attach gdb(1) to your process:
# gdb -p 20640
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
...
(gdb) bt
#0 0x00007fd1a99fd123 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:82
#1 0x0000000000405533 in ?? ()
#2 0x00007fd1a993deff in __libc_start_main (main=0x4043e3, argc=13, ubp_av=0x7fff25e7b478,
...
The backtrace is often the single most useful error report you can get from a process, so it is worth installing gdb(1) if it isn't already installed. gdb(1) can do a lot more than just show you backtraces, but a full tutorial is well outside the scope of Stack Overflow.
you can try with pstack passing pid as parameter. You can use ps to get the process id (pid)
For example: pstack 1267
I have a extremely complicated shell script, within which it calls a C++ program I want to debug via GDB. It is extremely hard to separate this c++ program from the shell since it has a lot of branches and a lot of environmental variables setting.
Is there a way to invoke GDB on this shell script? Looks like gdb requires me to call on a C++ program directly.
In addition to options mentioned by #diverscuba23, you could do the following:
gdb --args bash <script>
(assuming it's a bash script. Else adapt accordingly)
There are two options that you can do:
Invoke GDB directly within the shell script. This would imply that you don't have standard in and standard out redirected.
Run the shell script and then attach the debugger to the already running C++ process like so: gdb progname 1234 where 1234 is the process ID of the running C++ process.
If you need to do things before the program starts running then option 1 would be the better choice, otherwise option 2 is the cleaner way.
Modify the c++ application to print its pid and sleep 30 seconds (perhaps based on environment or an argument). Attach to the running instance with gdb.
I would probably modify the script to always call gdb (and revert this later) or add an option to call gdb. This will almost always be the easiest solution.
The next easiest would be to temporarily move your executable and replace it with a shell script that runs gdb on the moved program. For example, in the directory containing your program:
$ mv program _program
$ (echo "#!/bin/sh"; echo "exec gdb $PWD/_program") > program
$ chmod +x program
Could you just temporarily add gdb to your script?
Although the answers given are valid, sometimes you don't have permissions to change the script to execute gdb or to modify the program to add additional output to attach through pid.
Luckily, there is yet another way through the power of bash
Use ps, grep and awk to pick-out the pid for you after its been executed. You can do this by either wrapping the other script with your own or by just executing a command yourself.
That command might look something like this:
process.sh
#!/usr/bin/env bash
#setup for this example
#this will execute vim (with cmdline options) as a child to bash
#we will attempt to attach to this process
vim ~/.vimrc
To get gdb to attach, we'd just need to execute the following:
gdb --pid $(ps -ef | grep -ve grep | grep vim | awk '{print $2}')
I use ps -ef here to list the processes and their arguments. Sometimes, you'll have multiple instances of a program running and need to further grep down to the one you want
the grep -ve grep is there because the f option to ps will include the next grep in its list. If you don't need the command arguments for additional filtering, don't include the -f option for ps and ignore this piece
grep vim is where we're finding our desired process. If you needed more filtering, you could just do something like grep -E "vim.*vimrc" and filter down to exactly the process that you're trying to attach to
awk '{print $2}' simply outputs just the process' pid to stdout. Use $1 if you're using ps -e instead of ps -ef
My normal setup is to run such script that starts my process in 1 tmux pane and having typed something similar to the above in a bottom pane. That way if I need to adjust the filtering (for whatever reason), I can do it pretty quickly.
Usually though, it will be the same for a specific instance and I want to just attach automatically after its been started. I'll do the following instead:
runGdb.py
#!/usr/bin/env bash
./process.sh &
PID=$(ps -ef | grep -ve grep | grep -E "vim.*vimrc" | awk '{print $2}')
#or
#PID=$(ps -e | grep vim | awk '{print $1}')
gdb --pid $PID
This assumes that the original process can be safely run in the background.