I have a c++ program that works fine, however it needs to run for a long time. But while it is running I could continue to develop some parts of it. If I recompile my program, this will replace the binary with a new one. Does this will modify the behavior of the running program? Or are the process and the binary file two separate things once the program is launched?
More generally, what are the steps of a program execution?
On Linux, the process uses memory mapping to map the text section of the executable file and shared libraries directly into the running process memory. So if you could overwrite the executable file, it would affect the running process. However, writing into a file that's mapped for execution is prohibited -- you get a "Text file busy" error.
However, you can still recompile the program. If the compiler (actually the linker) gets this error, it removes the old executable file and creates a new one. On Unix, if you remove a file that's in use, the file contents are not actually removed from the disk, only the reference from the directory entry is removed; the file isn't fully deleted until all references to it (directory entries, file descriptors and memory mappings) go away. So the running process continues to be mapped to the old, nameless file. You can see this with the following demonstration:
barmar#dev:~$ ls -li testsleep
229774 -rwxr-xr-x 1 barmar adm 4584 Apr 24 04:30 testsleep
barmar#dev:~$ ./testsleep &
[1] 17538
barmar#dev:~$ touch testsleep.c
barmar#dev:~$ make testsleep
cc testsleep.c -o testsleep
barmar#dev:~$ ls -li testsleep
229779 -rwxr-xr-x 1 barmar adm 4584 Apr 24 04:32 testsleep
The inode number changed from 229774 to 229779 when I recompiled the program while it was running, indicating that a new file was created.
On Windows, you couldn't even write the new executable while the old version is running. The file on disk is locked while the process exists. On Linux, you can overwrite the file on disk, but the copy in memory remains untouched.
OTOH, while running in an IDE, it may be possible to patch the running process as the IDE is aware of the relevant details. But it's complex and not all IDE's support this.
Related
On the docker image debian:stretch-slim, couldn't delete a specific folder on a NFS drive, using rm -rf /folder-name as root (or rm-rf * after entering the folder-name).
Got the following error back:
rm: cannot remove 'test-ikmgfjhv/dev/.nfse47cf31c6b1dd52500000009': Device or resource busy
After a lot of searching, eventually got to the following link:
https://uisapp2.iu.edu/confluence-prd/pages/viewpage.action?pageId=123962105
Which Describes exactly why those files exist in NFS and how to handle them.
As I wasn't using the same machine the process runs on (another container), so in my case, I had to work around that and first make sure the process using the file is being killed on the first machine, then try to delete it on the second one, according to the project's needs.
It is possible that the .nfs file is attached to a process that is busy or running (like an open file, for example, a vim file).
For example, if the hidden file is .nfs000000000189806400000085, run this command to get the pid:
lsof .nfs000000000189806400000085
this will output the PID and other info related to that file
then kill the process:
kill - 9
Be aware that if the file was not saved you will lose the information.
While running any command if you get error like :
/home/mmandi/testcases/.nfs000000e75853 :device or resource busy.
Go to the directory where this file is being shown.
For e.g - In this case : /home/mmandi/testcases/
Do following :
# ls -la : This will display contents of the directory along with files starting with "."
Here it displays the .nfs000000e7585 file.
# lsof .nfs000000e7585
This will list down the PID
# Use Kill -9 PID.
In order to implement DFS on a huge graph in Dev c++ on a Windows 7 machine, I needed to increase the default stack size of 1 MB to 16 MB. I accomplished the same by creating a bat file in the folder as that of project with the text as..
g++ -Wl,--stack,16777216 -o project2.exe main.cpp
Every time I compile the program in Dev C++, it assigns the default stack value. I have to externally run this bat file and then run the exe file which consumes a lot of time.
Is there any way to directly add this command following the commands of compilation?
I tried adding this line in the Makefile but then the program doesn't compile.
I also tried adding it in compiler options but still comes the same issue.
Please suggest a method.
I have a .bat (Batch) file compiling an OS I am making in Windows 7. I use nasm to compile the code, then dd and imdisk. Although probably not worth mentioning, after compilation I use mkisofs to make a .iso then VirtualBox for testing.
When it gets past "Copying kernel and files to disk" it (the output in the prompt) says The volume does not contain a recognized file system. Please make sure that all required file system drivers are loaded and that the volume is not corrupted. 0 file(s) copied.
It compiled before in which I could properly test the OS and some text would appear, then I noticed nothing appeared on the screen anymore, so I further looked at the prompt output and batch file and realized this.
Can anyone give me some help here? I really want it to compile.
Here is the main part that errors in my batch file:
echo Adding boot to disk
cd build
dd if=..\src\boot\boot.bin bs=512 of=myos.flp
cd ..
echo Mounting disk image
imdisk -a -f build\myos.flp -s 1440K -m B:
echo Copying kernel and files to disk
copy src\kernel.bin b:\
echo Dismounting disk image
imdisk -D -m B:
I am able to successfully compile MikeOS (my inspiration) with pretty much the same commands (I modified the MikeOS buildwin.bat to use dd), so I have no idea what is happening.
EDIT: I even tried this in Ubuntu with dd and it doesn't work! When I get to the mount part it says something about the filesystem...I think my dd command is wrong, but for some reason I can compile MikeOS correctly. Ugh.
The boot file should always be in the first sector. Try this:
dd seek=0 if=..\src\boot\boot.bin bs=512 of=myos.flp
seek=0 copies the boot file to the first sector. If you don't put it, the dd command may copy the file to somewhere else.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Get path of executable
I'm programming on Windows using MinGW, gcc 4.4.3. When I use the main function like this:
int main(int argc, char* argv[]){
cout << "path is " << argv[0] << endl;
}
On Windows I get a full path like this: "C:/dev/stuff/bin/Test". When I run the same application on Linux, however, I get some sort of relative path: "bin/Test". It's breaking my application! Any idea on how to make sure the path is absolute on both systems?
No, there isn't. Under most shells on Linux, argv[0] contains exactly what the user typed to run the binary. This allows binaries to do different things depending on what the user types.
For example, a program with several different command-line commands may install the binary once, and then hard-link the various different commands to the same binary. For example, on my system:
$ ls -l /usr/bin/git*
-rwxr-xr-x 109 root wheel 2500640 16 May 18:44 /usr/bin/git
-rwxr-xr-x 2 root wheel 121453 16 May 18:43 /usr/bin/git-cvsserver
-rwxr-xr-x 109 root wheel 2500640 16 May 18:44 /usr/bin/git-receive-pack
-rwxr-xr-x 2 root wheel 1021264 16 May 18:44 /usr/bin/git-shell
-rwxr-xr-x 109 root wheel 2500640 16 May 18:44 /usr/bin/git-upload-archive
-rwxr-xr-x 2 root wheel 1042560 16 May 18:44 /usr/bin/git-upload-pack
-rwxr-xr-x 1 root wheel 323897 16 May 18:43 /usr/bin/gitk
Notice how some of these files have exactly the same size. More investigation reveals:
$ stat /usr/bin/git
234881026 459240 -rwxr-xr-x 109 root wheel 0 2500640 "Oct 29 08:51:50 2011" "May 16 18:44:05 2011" "Jul 26 20:28:29 2011" "May 16 18:44:05 2011" 4096 4888 0 /usr/bin/git
$ stat /usr/bin/git-receive-pack
234881026 459240 -rwxr-xr-x 109 root wheel 0 2500640 "Oct 29 08:51:50 2011" "May 16 18:44:05 2011" "Jul 26 20:28:29 2011" "May 16 18:44:05 2011" 4096 4888 0 /usr/bin/git-receive-pack
The inode number (459240) is identical and so these are two links to the same file on disk. When run, the binary uses the contents of argv[0] to determine which function to execute. You can see this (sort of) in the code for Git's main().
argv array
argv[0] is a parameter like any others: it can be an arbitrary NUL terminated byte string. It can be the empty string. It is whatever the launching process wants.
By default, the shell with set argv[0] to whatever is used to name the program: a name looked-up in $PATH, a relative or an absolute path. It can be a symbolic link or a regular file.
To invoke a program with some other value, with zsh (dunno with other shells) use:
ARGV0=whatever_you_want some_program arguments
If you really need the path to the executable, you cannot use the command line on Unix.
Linux only
On Linux: /proc/self/exe is a symbolic link to the executable file.
You can readlink it. You can also stat or open it directly.
Renaming and soft link
A normal soft link is a dumb string, and doesn't know what happens to its target (if it exists at all). But the /proc/self/exe soft link is magic.
In case of renaming, the soft-but-magic-link will follow renaming. In case there are several hard links, it will follow the name of the particular hard link that was used. (So different hard links to the same file are not perfectly equivalent under Linux.)
If this hard link is unlinked, I think " (deleted)" is appended to the value of the symbolic link. Note that this is a valid file name, so another unrelated file could have that name.
In any case, the symbolic link is a hard link to the file, so you can stat or open it directly.
I don't think you can count on anything on a network file system if the binary is renamed or unlinked on another system than the one where the executable is launched.
Security considerations
When your program gets to use the /proc/self/exe special file, it is possible for the file used to launch your program to be unlinked or renamed. This should be taken seriously in case the program is privileged (SUID or Set Capabilities): even if the user doesn't have write access to the original "Set Something" binary, he may be able to make a hard link to it if he has write access to a directory on the same file system, so he may be able to change the name if a running privileged binary.
By the time you readlink, the value returned may refer to another file. (Of course, there is always an unavoidable race condition with opening the result of readlink.)
As usual, NFS does not provides all the same guaranties that local file systems have.
There is no way to ensure that argv[0] is an absolute path because it is supposed to be exactly how the user invoked the program. So, if on a Linux command line you invoke your program via ./bin/Test, then argv[0] should be exactly "./bin/Test".
It seems like a bug in MinGW's runtime if when you invoke the program from a command prompt via .\bin\Test, argv[0] is "C:/dev/stuff/bin/Test". With the latest MinGW (gcc version 4.5.2), invoking a binary via .\bin\Test means argv[0] is ".\bin\Test". A Microsoft Visual C++-built binary (cl version 16.00.40219.01) invoked via .\bin\Test also has ".\bin\Test" for argv[0].
I'm using Linux redhat 3, can someone explain how is that possible that i am able to analyze
with gdb , a core dump generated in Linux redhat 5 ?
not that i complaint :) but i need to be sure this will always work... ?
EDIT: the shared libraries are the same version, so no worries about that, they are placed in a shaerd storage so it can be accessed from both linux 5 and linux 3.
thanks.
You can try following commands of GDB to open a core file
gdb
(gdb) exec-file <executable address>
(gdb) set solib-absolute-prefix <path to shared library>
(gdb) core-file <path to core file>
The reason why you can't rely on it is because every process used libc or system shared library,which will definitely has changes from Red hat 3 to red hat 5.So all the instruction address and number of instruction in native function will be diff,and there where debugger gets goofed up,and possibly can show you wrong data to analyze. So its always good to analyze the core on the same platform or if you can copy all the required shared library to other machine and set the path through set solib-absolute-prefix.
In my experience analysing core file, generated on other system, do not work, because standard library (and other libraries your program probably use) typically will be different, so addresses of the functions are different, so you cannot even get a sensible backtrace.
Don't do it, because even if it works sometimes, you cannot rely on it.
You can always run gdb -c /path/to/corefile /path/to/program_that_crashed. However, if program_that_crashed has no debug infos (i.e. was not compiled and linked with the -g gcc/ld flag) the coredump is not that useful unless you're a hard-core debugging expert ;-)
Note that the generation of corefiles can be disabled (and it's very likely that it is disabled by default on most distros). See man ulimit. Call ulimit -c to see the limit of core files, "0" means disabled. Try ulimit -c unlimited in this case. If a size limit is imposed the coredump will not exceed the limit size, thus maybe cutting off valuable information.
Also, the path where a coredump is generated depends on /proc/sys/kernel/core_pattern. Use cat /proc/sys/kernel/core_pattern to query the current pattern. It's actually a path, and if it doesn't start with / then the file will be generated in the current working directory of the process. And if cat /proc/sys/kernel/core_uses_pid returns "1" then the coredump will have the file PID of the crashed process as file extension. You can also set both value, e.g. echo -n /tmp/core > /proc/sys/kernel/core_pattern will force all coredumps to be generated in /tmp.
I understand the question as:
how is it possible that I am able to
analyse a core that was produced under
one version of an OS under another
version of that OS?
Just because you are lucky (even that is questionable). There are a lot of things that can go wrong by trying to do so:
the tool chains gcc, gdb etc will
be of different versions
the shared libraries will be of
different versions
so no, you shouldn't rely on that.
You have asked similar question and accepted an answer, ofcourse by yourself here : Analyzing core file of shared object
Once you load the core file you can get the stack trace and get the last function call and check the code for the reason of crash.
There is a small tutorial here to get started with.
EDIT:
Assuming you want to know how to analyse core file using gdb on linux as your question is little unclear.