Found this example in the net and can't find out why this line wouldn't be printed
#include<stdlib.h>
#include<unistd.h>
int main()
{
pid_t return_value;
printf("Forking process\n");
return_value=fork();
printf("The process id is %d
and return value is %d\n",
getpid(), return_value);
execl("/bin/ls/","ls","-l",NULL);
printf("This line is not printed\n");
}
A successful execl never returns, see the man page:
The exec() functions only return if an error has occurred.
Instead, the host process is replaced by what you are execing, in this case, the ls process image:
The exec() family of functions replaces the current process image with a new process image.
This way, your program will be replaced in memory before reaching the last printf statement, causing it to never execute.
exec*() functions is a special in sense that they are non-returning. Typical implementation of that function "replaces" modules of current process that is effectively the same as starting of new program right inside of current process. In your case new program is /bin/ls. During execl() all previous images are unloaded from process, then /bin/ls and all its dependencies are loaded and control is passed to entry point of /bin/ls, that calls its main() function, so on.
Thus there is no place to return control after execl() since module that calls it no more exists in address space of current process.
Related
How to run any exe file from turbo c++? I know that I should stop using turbo c++ and move one to Dev or Code::Blocks, but my school doesn't agree so I gotta wing it.
I just want to know how to run a file with or without the system() function.
Any kind of advice is welcome
Here's what I have tried so far:
1
#include<process.h>
int main()
{
system("tnfsv13.exe"); //tnfsv being a 16-bit application(The need for slowness v 13)
return 0;
}
2
#include<process.h>
int main()
{
system("tnfsv13.bat");
return 0;
}
tnfsv13.bat:
start "c:\TurboC3\BIN\" tnfsv13.exe
NOTE: Just a doubt, you guys: system() is not working in windows XP. I tried it using dosbox in windows 7 and it works well, but in XP it does absolutely nothing. Not even the system("dir") command seems to work but system(NULL) returns 1. Any guesses why?
Thanks.
You can also use Turbo C++'s execl() function. execl() loads and runs C:\\TC\\BIN\\tnfsv13.exe. NULL means there are no arguments to send to tnfsv13.exe. If an error occurs, execl() returns -1 into int c .
#include<stdio.h>
#include<process.h>
int main()
{
int c = execl("C:\\TC\\BIN\\tnfsv13.exe", NULL);
return 0;
}
Explanation:
execl() loads and executes a new child process. Because the child
process is placed in the memory currently occupied by the calling
process, there must be sufficient memory to load and execute it.
'pathname' specifies the file name of the child process. If
'pathname' has a file name extension, then only that file is searched
for. If 'pathname' ends with a period (.), then 'pathname' without an
extension is searched for. If that filename is not found, then
".EXE" is appended and execl() searches again. If 'pathname' has no
extension and does not end with a period, then execl() searches for
'pathname' and, if it is not found, appends ".COM" and searches
again. If that is not found, it appends ".EXE" and searches again.
'arg0', 'arg1',...'argn' are passed to the child process as command-
line parameters. A NULL pointer must follow 'argn' to terminate the
list of arguments. 'arg0' must not be NULL, and is usually set to
'pathname'.
The combined length of all the strings forming the argument list
passed to the child process must not exceed 128 bytes. This includes
"n" (for 0-n arguments) space characters (required to separate the
arguments) but does not include the null ('\0') terminating
character.
Returns: If execl() is successful, it does not return to the
calling process. (See the spawn...() routines for a
similar function that can return to the calling
process). If an error occurs, execl() returns -1 to
the calling process. On error, 'errno' (defined in
<errno.h>) is set to one of the following values
(defined in <errno.h>):
E2BIG Argument list or environment list too big.
(List > 128 bytes, or environment > 32k)
EACCES Locking or sharing violation on file.
(MS-DOS 3.0 and later)
EMFILE Too many files open.
ENOENT File or path not found.
ENOEXEC File not executable.
ENOMEM Not enough memory.
Notes: Any file open when an exec call is made remains open
in the child process. This includes
'stdin','stdout', 'stderr', 'stdaux', and 'stdprn'.
The child process acquires the environment of the
calling process.
execl() does not preserve the translation modes of
open files. Use setmode() in the child process to
set the desired translation modes.
See the spawn...() routines for similar though more
flexible functions that can return to the calling
program.
Caution: The file pointers to open buffered files are not
always preserved correctly. The information in the
buffer may be lost.
Signal settings are not preserved. They are reset to
the default in the child process.
-------------------------------- Example ---------------------------------
The following statements transfer execution to the child process
"child.exe" and pass it the three arguments "child", "arg1",
and"arg2":
#include <process.h> /* for 'execl' */
#include <stdio.h> /* for 'printf' and 'NULL' */
#include <errno.h> /* for 'errno', 'ENOENT' and 'ENOMEM' */
main()
{
execl("child.exe", "child", "arg1", "arg2", NULL);
/* only get here on an exec error */
if (errno == ENOENT)
printf("child.exe not found in current directory\n");
else if (errno == ENOMEM)
printf("not enough memory to execute child.exe\n");
else
printf(" error #%d trying to exec child.exe\n", errno);
}
system() works fine, though it may not work exactly the way you expect: it does the same thing as typing a command at a MSDOS (or Win32) command prompt including input and output being connected to the console.
If you just want to run a program, pass parameters, and not return from it, use a convenient form from the exec() family of functions. See this for one example.
I have the following function from a book titled "Advanced Linux Programming".
int spawn (char* program, char** arg_list)
{
pid_t child_pid;
/* Duplicate this process. */
child_pid = fork ();
if (child_pid != 0)
/* This is the parent process. */
return child_pid;
else {
/* Now execute PROGRAM, searching for it in the path. */
execvp (program, arg_list);
/* The execvp function returns only if an error occurs. */
fprintf (stderr, “an error occurred in execvp\n”);
abort ();
}
}
But I'm confused that, in cases where ls is executed successfully, the error is not printed, but in case it fails, it prints the error which is put in the line following it.
My Question
This line fprintf (stderr, “an error occurred in execvp\n”); is after the execvp() function, and it is expected to be executed after the execution of execvp() finishes, but it is not the case, and it is executed only if execvp() encounters an error. It seems the function spawn() finishes as soon as it executes execvp() successfully. Am I right?
You can have a look at the manpage for execvp, it says:
The exec() family of functions replaces the current process image with
a new process image.
So, what does that mean? It means, if execvp succeeds, your program wont be in memory anymore, thus it wont ever reach the error message. Your program in memory will be replaced by the new program (in your case ls if i understood it correctly).
So, if your program is able to reach the error message printout, then the execvp function will have failed. Otherwise the other program starts execution.
The reason why your programm will be still running is the fork command, which creates a copy of the process image, so you will be having two same processes running of which only one will be replaced by the command you try to execute. This is achieved by the if clause if (child_pid != 0), as the fork command will duplicate the process and return the new Process ID (PID). If this is set to 0 (see man 3 fork), then its the new child process, if its != 0 its the parent process. Your function there only executes execvp if its the child process, the parent process encounters an early return.
I am trying to debug a server application but I am running into some difficulties breaking where I need to. The application is broken up into two parts:
A server application, which spawns worker processes (not threads) to handle incoming requests. The server basically spawns off processes which will process incoming requests first-come first-served.
The server also loads plugins in the form of shared libraries. The shared library defines most of the services the server is able to process, so most of the actual processing is done here.
As an added nugget of joy, the worker processes "respawn" (i.e. exit and a new worker process is spawned) so the PIDs of the children change periodically. -_-'
Basically I need to debug a service that's called within the shared library but I don't know which process to attach to ahead of time since they grab requests ad-hoc. Attaching to the main process and setting a breakpoint hasn't seemed to work so far.
Is there a way to debug this shared library code without having to attach to a process in advance? Basically I'd want to debug the first process that called the function in question.
For the time being I'll probably try limiting the number of worker processes to 1 with no respawn, but it'd be good to know how to handle a scenario like this in the future, especially if I'd like to make sure it still works in the "release" configuration.
I'm running on a Linux platform attempting to debug this with DDD and GDB.
Edit: To help illustrate what I'm trying to accomplish, let me provide a brief proof on concept.
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
int important_function( const int child_id )
{
cout << "IMPORTANT(" << child_id << ")" << endl;
}
void child_task( const int child_id )
{
const int delay = 10 - child_id;
cout << "Child " << child_id << " started. Waiting " << delay << " seconds..." << endl;
sleep(delay);
important_function(child_id);
exit(0);
}
int main( void )
{
const int children = 10;
for (int i = 0; i < 10; ++i)
{
pid_t pid = fork();
if (pid < 0) cout << "Fork " << i << "failed." << endl;
else if (pid == 0) child_task(i);
}
sleep(10);
return 0;
}
This program will fork off 10 processes which will all sleep 10 - id seconds before calling important_function, the function in which I want to debug in the first calling child process (which should, here, be the last one I fork).
Setting the follow-fork-mode to child will let me follow through to the first child forked, which is not what I'm looking for. I'm looking for the first child that calls the important function.
Setting detach-on-fork off doesn't help, because it halts the parent process until the child process forked exits before continuing to fork the other processes (one at a time, after the last has exited).
In the real scenario, it is also important that I be able to attach on to an already running server application who's already spawned threads, and halt on the first of those that call the function.
I'm not sure if any of this is possible since I've not seen much documentation on it. Basically I want to debug the first application to call this line of code, no matter what process it's coming from. (While it's only my application processes that'll call the code, it seems like my problem may be more general: attaching to the first process that calls the code, no matter what its origin).
You can set a breakpoint at fork(), and then issue "continue" commands until the main process's next step is to spawn the child process you want to debug. At that point, set a breakpoint at the function you want to debug, and then issue a "set follow-fork-mode child" command to gdb. When you continue, gdb should hook you into the child process at the function where the breakpoint is.
If you issue the command "set detach-on-fork off", gdb will continue debugging the child processes. The process that hits the breakpoint in the library should halt when it reaches that breakpoint. The problem is that when detach-on-fork is off, gdb halts all the child processes that are forked when they start. I don't know of a way to tell it to keep executing these processes after forking.
A solution to this I believe would be to write a gdb script to switch to each process and issue a continue command. The process that hits the function with the breakpoint should stop.
A colleague offered another solution to the problem of getting each child to continue. You can leave "detach-on-fork" on, insert a print statement in each child process's entry point that prints out its process id, and then give it a statement telling it to wait for the change in a variable, like so:
{
volatile int foo = 1;
printf("execute \"gdb -p %u\" in a new terminal\n", (unsigned)getpid());
printf("once GDB is loaded, give it the following commands:\n");
printf(" set variable foo = 0\n");
printf(" c\n");
while (foo == 1) __asm__ __volatile__ ("":::"memory");
}
Then, start up gdb, start the main process, and pipe the output to a file. With a bash script, you can read in the process IDs of the children, start up multiple instances of gdb, attach each instance to one of the different child processes, and signal each to continue by clearing the variable "foo".
I am writing a small shell program that takes a command and executes it. If the user enters a not valid command the if statement returns a -1. If the command is correct it executes the command, however once it executes the command the program ends. What am I doing wrong that is does not execute the lines of code after it? I have tested execvp( command.argv[0], command.argv) with ls and cat commands so I am pretty sure it works. Here is my code.
int shell(char *cmd_str ){
int commandLength=0;
cmd_t command;
commandLength=make_cmd(cmd_str, command);
cout<< commandLength<<endl;
cout << command.argv[0]<< endl;
if( execvp( command.argv[0], command.argv)==-1)
//if the command it executed nothing runs after this line
{
commandLength=-1;
}else
{
cout<<"work"<<endl;
}
cout<< commandLength<<endl;
return commandLength;
}
From man page of execvp(3)
The exec() family of functions replaces the current process image with
a new process image
So your current process image is overwritten with the image of your command! Hence you need to use a fork+exec combination always so that your command executes in the child process and your current process continues safely as a parent!
On a lighter note I want to illustrate the problem with a picture as a picture speaks a thousand words. No offence intended :) :)
From the documentation on exec
The exec() family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for execve(2). (See the manual page for > execve(2) for further details about the replacement of the current process image.)
If you want your process to continue, this is not the function you want to use.
#Pavan - Just for nit-pickers like myself, technically the statement "current process is gone" is not true. It's still the same process, with the same pid, just overwritten with a different image (code, data etc).
I'm really new to C programming, although I have done quite a bit of other types of programming.
I was wondering if someone could explain to me why this program outputs 10.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int value = 10;
int main()
{
pid_t pid;
pid = fork();
if(pid == 0){
value += 10;
}
else if(pid > 0){
wait(NULL);
printf("parent: value = %d\n", value); //Line A
exit(0);
}
}
I know the output is "parent: value = 10". Anyone know why?
Thanks!
fork creates two processes (the "parent" and the "child"). Each process has a different value of pid in your example. The child process has a pid of 0. The parent process has a pid of the child's operating system pid (assigned by the OS.)
In your example, each process has it's own value in its memory. They do not share memory (like you think they should by your question.) If you change one process (the first part of the if) it will not be reflected in the second process (the second part of the if.)
Edit: Explained the value of pid.
About fork() :
If fork() returns a negative value,
the creation of a child process was
unsuccessful.
If fork() returns a zero to the newly
created child process.
If fork() returns a positive value, the
process ID of the child process, to
the parent.
So in you case it bound to return a number greater than 0 & thus the value will remain 10 & will be printed.
Well, fork spawns a new process. It more or less copies the current process, and both the new one (the child) and the old one (the parent) go on at the same point in the code. But there is one significant difference (that interests us) here: for the child, fork returns 0. For the parent, it returns the process ID of the child.
So the if(pid ==0) part is true for the child. The child simple add 10 to his value, and then exits since there is no further code.
The else part is true for the parent (except for the very rare case that fork returned an error with -1). The parent simply waits for the child to exit. But the child has modified its own copy of value, the one of the parent is still untouched and that is why you get the output of "10". Then the parent also exits.
fork() creates a new process: it has two return values in two different contexts, so both paths run in your if statement. The conditional is mostly used to determine which process you run in after the fork.
when you call fork, it creates a copy of the process in such a way that both the copies' program counters are at the same position in their code sections. Hence when any of these copies resumes execution, both will just be finishing the call to fork.
So both of them should execute identically.
BUT, fork returns 0 in the child process, and the pid of the child process in the parent process.
That explains the mojo behind the if( pid==0 ) part.
So when the child process changes the value of value, it actually changes that in its own copy (remember: the process got copied, so the data sections got copied too).
Meanwhile, the parent process executes with its old value of value, which is 10.
Even after the child changes its copy of value and dies, the parent's copy is still 10.
The fork system call creates a new process as a child of the existing (parent) process. Both the parent and the child continue execution at the line following the fork statement, however the child process is given an exact copy of the parents address space.
The fork system call returns the process id of the newly created process to the parent and zero to the child, therefore within this code the child will increment its own copy of the value variable and the parent will print out its own copy.
You will often see fork followed by an exec within the child so that it replaces itself with another program.