I have a weird behavior with the value of filename in /proc/pid/stat.
My program's name is "test_dev", and when I execute it with "./test_dev" and i look on /proc/pid/stat, i see "pid (test) ....".
Same in /proc/pid/status.
I change "test_dev" to "testdev" to see if the underscore is the culprit of this mess, but the same thing appear again.
I printf argv[0], and I correctly see "test_dev" (or "testdev").
I wonder how the field in stat is set, and why it's incomplet, because the man of /proc say that is the filename of the executable.
I think a little, and I wonder if Eclipse can be the culprit.
This EDI gave me some surprise sometimes, and I won't be surprised if this is the case again, even if it really bug me that argv[0] and /proc/pid/stat have not the same value.
Is somebody have an explanation ?
thanks.
However, the real filename without "_dev" is 15 character long, and
the "comm" field seem to be limited by the kernel to 15 character long
... So, the filename is truncated in /proc/pid/stat, … Where can I
find this kind of documentation ?
Unfortunately, this seems to be not well documented where one would expect it, but there are some hints here and there on the proc man page.
/proc/[pid]/comm (since Linux 2.6.33)
… Strings longer than TASK_COMM_LEN (16) characters are silently truncated.
/proc/[pid]/stat
Status information about the process. This is used by ps(1).
It is defined in the kernel source file fs/proc/array.c.
TASK_COMM_LEN and the task_struct are defined in include/linux/sched.h:
#define TASK_COMM_LEN 16
…
struct task_struct {
…
char comm[TASK_COMM_LEN];
The difference between the 15 characters you observe and the 16 here is due to the terminating '\0'.
The field in /proc/pid/stat you mention does not show argv[0], but the executed command. Probably, eclipse compiles the file to an executable named "test" and executes it.
This example:
execl("foo", "bar", "baz", NULL);
has a comm of "foo" (the thing in /proc/pid/stat), an argv[0] of "bar" and "baz" as argv[1]
To double-check that, you might try to call your program "xxxxx" and see, if it is still named "test" in /proc/pid/stat
Related
I run the following C code to create a process. The exe file is located at C:\Program Files\Exes\Start\process1.exe
CreateProcessW(NULL, (char*) exePath,
NULL, NULL, TRUE,
flags,
NULL, NULL, &startupInfo, &processInformation);
Now some computers randomly have this file called Program located at C:\Program which causes create process to fail with the error:
%1 is not a valid Win32 application.
Is there a way to fix this problem apart from renaming the file because there are a few dozen Windows Vms on which this C code is executed. This error randomly happens on a few machines.
How does this code even compile? The second parameter to CreateProcessW is defined as a LPWSTR which means it should only accept a wide string.
The next problem: as a result of the cast it's not possible to determine what the source of exePath is. The reason this is of consequence is that the 2nd parameter is defined as a LPWSTR, not a LPCWSTR (i.e. a const wide string) for a reason: CreateProcessW may write to the buffer.
Then the 3rd problem - your exe path had a space in it. When passed as the 2nd parameter (lpCommandLine) CreateProcess has some derpy logic to guess where the exe name ends and the command line begins. Which necessitates quote encoding the exe path part of the command line.
When you have the full path to the exe - and no parameters - the simplest / safest thing to do is to just pass it as the lpApplicationName parameter. This IS a const parameter which avoids any potential undefined behaviour that could result if your command line source was a constant string literal etc. And is simply used as the path to the exe to execute, so does not (and can not) have any quoting requirements.
CreateProcess(exePath,NULL,...);
Aside: Using both parameters to CreateProcess essentially lets you set argv[0] of the launched application to be anything you want. So you could run an application from a particular path / exe name, but make argv[0] point at some other path or exe name.
To pass a parameter to the exe, rather than passing the full (quote enclosed) path you could do something simple like this:
WCHAR cmdLine[] = TEXT("console1.exe --version");
CreateProcessW(exePath,cmdLine,...);
Edits Credit to Paul Sanders and the other comments for pointing out the unquoted exe path, and also caused me to completely break my original answer which had solved that without me realising it.
Credit to RbMm for spotting I had broken my answer, and credit to eryksun for showing me that I've been reading the documentation wrong for almost 20 years now.
Chris makes a lot of good points there and you should take them on board, but the real issue, as immibis says, is that you are using the CreateProcess API incorrectly. The way you've done it requires exepath to be quoted, if it contains any whitespace.
So, instead, after you've fixed all the issues that Chris has raised, do this:
CreateProcessW (exePath, NULL,
NULL, NULL, TRUE,
creation_flags,
NULL, NULL, &startupInfo, &processInformation);
i.e. just swap the first and second parameters around (and perhaps use a more descriptive name for flags, as I've done here).
You can pass any command line arguments you might need in that second parameter, if that ever becomes a requirement. And please, read the docs.
Edit (to get my rep back :)
Also, as Chris says, exepath needs to be a wide string here, so I took out your (redundant) cast which would in fact generate a compiler error (C++) or warning (C) (so, a warning, guess, since your post is tagged As C, thank you #Barmak).
Anyway, if you now don't get one, then exepath must in reality already be a wide string so all is well. If not, then you obviously need to fix that, but I imagine this whole issue is just a typo in your post since you clearly did have your code working in order to report the behaviour you are observing.
I have a function that pretty prints a data structure, its function prototype is:
void print_mode(FILE *fp, Mode *mode);
the FILE* allows you to redirect the output to anywhere you want, e.g. stdout, stderr, a file etc. Mode is the data structure
I am trying to call this function from within gdb and want the output to be directed to the gdb console window, stdout?
I have tried:
(gdb) p print_mode(STDOUT,fragment_mode)
No symbol "STDOUT" in current context.
(gdb) p print_mode(stdout,fragment_mode)
$17 = void
neither of which work
any ideas how i can get the output of the function to display in the gdb console?
should add - I am using gdb within emacs 24.2.1 under linux
STDOUT seems to be macro, which is not know to GDB, as handled prior to compilation by the pre-preprocessor.
Using stdout should do the job.
However the function print_mode() simply does not seem to print out anything.
In terms what's being printed to the console by the program being debugged, GDB's commands printand call should not make a difference.
For details on this you might like to read here: https://sourceware.org/gdb/onlinedocs/gdb/Calling.html
An issue might be that stdout by default is line buffered, so output would not occur before detecting a linefeed and print_mode() perhaps does not send a linefeed (\n).
To test this just use stderr as output file, as the latter isn't buffered:
p print_mode(stderr, fragment_mode)
Oh dear - silly mistake. You're right, stdout does do the job.
I forgot that having upgraded from emacs 23 to 24, the way gdb works has changed in as much as it now opens a separate buffer *input/output of program-name* to which it redirects the output of the program being debugged. In the prior version of emacs it was all displayed in the same, single gdb buffer.
So my second attempt was actually working, I was just looking in the wrong place so didn't see the output
I am very new with c and less experienced with any other language :/
For an assignment at uni, I am a little stuck on this small part. Essentially I am required to write a 'ls' function that has 4 optional arguments, for example:
list [-l] [-f] [pathname] [localfile]
Now, the first two are straight forward. To make things more difficult, the 'localfile' doesn't necessarily exist and the 'pathname'(if given) will be located on the server I'm connecting to through a socket (so checking if it is a file is out and checking the pathname is out). I was thinking, check last 4 chars in the string for a '.txt' or something similar. I'm actually completely stumped and will present this problem to my course conveyor tomorrow, if I can't find a solution.
This is a very small part of what I actually have to do but any push in the right direction would be appreciated.
You will need to process argc and argv to get your command line arguments. That is the first thing to work on, getting the arguments - ensuring they are correct, and determining what is being asked for.
int main(int argc, char *argv[])
Assuming your are on Linux/Unix, you will need to use the directory functions opendir()/readdir()/closedir() - dirent.h. The stat() function will be required to satisfy the -l requirement. access() will determine if a file exists and then stat() will tell you if the file is a regular file or a directory.
I'd make a struct to hold the four optional arguments and return it from a function called "process_arguments" that takes argc and argv as parameters.
struct args {
bool valid;
bool l_option;
bool f_option
char directory[200];
char filename[200];
}
With the requirement for a socket connection you will have to write a "server program" that will be constantly running on the server and a "client program" that it will fork to handle the requests from your local program. Try and locate examples of socket programs.
Another check for whether you have a path string or a filename is to look for the path separator character - '/' if the server is Unix/Linux. This scheme shouldn't have any path separators in filenames, so the presence of one tells you it is a path.
This is a simple C program that prints the number of command line argument passed to it:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("%d\n", argc);
}
When I give the input
file_name *
It prints 623 instead of 2 in my pc (operating system Windows 7). But it gives the correct output in other cases. Is * a reserved character for command line arguments?
Note this program gives correct output for the following input:
file_name *Rafi
Output = 2
On a Unix command line, the shell is responsible for handling wildcards. yourapp * will run yourapp, and pass the name of ALL of the non-hidden files in the current directory as arguments. In your case, that's 622 files (623 = 622 files + name of the program).
On Windows, applications are responsible for wildcard parsing, so argc is 2, 1 for the name of the program (argv[0]) and 1 for the wildcard (argv[1] = *);
That * gets expanded by the shell or the runtime library (the former on *nixes, the latter on Windowses), and instead of literal * you get the names of all the files in the current working directory.
As others have mentioned, you're getting the 'shell wildcard expansion' or 'globbing' where the * is used as a wildcard to match file names to place in the argv array.
On Unix systems this is performed by the shell and has nothing (or little) to do with the C runtime.
On Windows systems, this functionality is not performed by the shell (unless possibly if you're using some Unix-like shell replacement like Cygwin). The globbing functionality may or may not be performed by the C runtime's initialization depending on what tools and/or linker options you use:
if you're using Microsoft's compiler, the C runtime will not perform globbing by default, and you would get an argc value of 2 in your example. However, if you ask the linker to link in setargv.obj (or wsetargv.obj if you have a Unicode build), then globbing is added to the runtime initialization and you'll get behavior similar to Unix's. setargv.obj has been distributed with MSVC for as long as I can remember, but it's still little known. I believe that most Windows programs perform their own wildcard expansion.
if you're using the MinGW/GCC tool chain, the C runtime will perform globbing before calling main() (at least it does for MinGW 4.6.1 - I suspect it's been in MinGW for a long time). I think MinGW might not perform globbing for GUI programs. You can disable MinGW's globbing behavior with one of the following:
define a global variable named _CRT_glob and initialize it to 0:
int _CRT_glob = 0;
link in the lib/CRT_noglob.o object file (I think this might be order dependent - you may need to place it before any libraries):
gcc c:/mingw/lib/CRT_noglob.o main.o -o main.exe
The problem is that the shell expands * into all the file names (that don't start with a .) in the current directory. This is all about the shell and very little to do with the C program.
The value of argc includes 1 for the program's own name, plus one for each argument passed by the shell.
Try:
filename *
filename '*'
The first will give you 623 (give or take - but it is time you cleaned up that directory!). The second will give you 2.
I'm using opendir / readdir / closedir to reproduce a program similar to ls, it went pretty well until I tried to ls "/dev/" when it comes to "/dev/fd/" with the recursive options, it find more files than it actually exists, those are not hidden files (I mean '.' commencing files ).
The true ls give me :
"/dev/fd/ :"
"0 1 2 3"
Mine too.
But, the thing is that in gdb, it find 3 more files that are 4,5 and 6. I heard that gdb create his own environement so let's forget this.
When I try ls "/dev/fd/" -R the true ls stop immediately the listing while my program gives :
"/dev/fd/3:"
"/dev/fd/3/3/"
"/dev/fd/3/3/......../10"
stat return -1 after 40 files at least but the execution continues : segmentation fault.
In my computer, "/dev/fd/3/" and so are symbolic links, the macro "S_ISDIR" returns me 0 on the existing files but on the non existing files like : "/dev/fd/6/" it return 1...
I wanted to know why my program goes wrong while the true ls doesn't, I noticed that ls use stat64 in my computer but when I do it still goes wrong.. it also use fstat64, futex and others syscall that I don't know.
I can show you some sample of my codes or detail a bit more it's really hard to explain for me I'm sorry for that.
Thanks you.
PS : I don't get that statement in the readdir manpage : "The data returned by readdir may be overwritten by subsequent calls to readdir for the same directory stream"
PS : I don't get that statement in the readdir manpage : "The data
returned by readdir may be overwritten by subsequent calls to readdir
for the same directory stream"
What they are basically saying is that the function is not re-entrant, and that the pointer returned by readdir shouldn't simply be cached as a unique value, as the underlying data that is being pointed to will change the next time you call the readdir function. Basically they are allowing for implementations to either define statically allocated data that can be recycled by the function, or dynamic memory managed by the OS, so that the caller of readdir does not have to worry about managing the memory pointed to by the return value of readdir. For instance, for a sample function like:
int* my_sample_increment()
{
static int val = 0;
val++;
return &val;
}
if you were to-do something like
int* int_ptr_1 = my_sample_increment();
int* int_ptr_2 = my_sample_increment();
Then both int_ptr_1 and int_ptr_2 will point to the same value, and in this case it will be the value 1. Each pointer won't be pointing to a unique integer value.
So the same is true with readdir. You cannot simply call readdir and store the pointer being returned, expecting to use it at a later date without the data that is being pointed to being modified by any subsequent calls to readdir between the time you saved the pointer, and the time you use it. If you need such functionality, that is what the re-entrant version, readdir_r is for.