![]() |
| | #1 |
| Registered User Join Date: Oct 2003
Posts: 92
| Code: int spawn( char* program, char** arg_list ) {
pid_t child_pid;
child_pid = fork();
if( child_pid != 0 )
return child_pid;
else {
execvp( program, arg_list );
}
}
mpg321 inputfiles.mp3 -w inputfiles.wav ( takes about 10+ seconds ) oggenc inputfiles.wav ( takes about 30+ seconds ) rm inputfiles.wav ( takes about 1- seconds ) Here's my program : Code: .....
switch(type) {
case mp3: arg_list[0] = "mpg321";
song.copy( arg_list[1], songlength, 0 );
arg_list[1][songlength] = '\0';
arg_list[2] = "-w";
outputsong.copy( arg_list[3], outputsonglength, 0 );
arg_list[3][outputsonglength] = '\0';
arg_list[4] = NULL;
spawn("mpg321", arg_list);
wait(&childstatus);
arg_list[0] = "oggenc";
outputsong.copy( arg_list[1], outputsonglength, 0 );
arg_list[1][outputsonglength] = '\0';
arg_list[2] = NULL;
spawn("oggenc", arg_list);
wait(&childstatus);
arg_list[0] = "rm";
outputsong.copy( arg_list[1], outputsonglength, 0 );
spawn("rm", arg_list);
wait(&childstatus);
break;
..........
To make it short, I have 3 commands to execute and I want it done in order. So command number 2 will wait command number 1 finish its processing. But in their processing, I want to manipulate my application's window. Any idea, guyz?????
__________________ A man asked, "Who are you?" Buddha answered, "I am awaked." |
| gandalf_bar is offline | |
| | #2 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,680
| So use another process Code: switch(type) {
case mp3: do_mp3(); break;
Code: void do_mp3 ( void ) {
if ( fork() == 0 ) {
// child process to do the conversions, and idle around waiting for things to finish
arg_list[0] = "mpg321";
// etc etc
_exit( 0 ); // it's done all it needs to, just exit
}
}
|
| Salem is offline | |
| | #3 |
| Registered User Join Date: Oct 2003
Posts: 92
| After couples day, I have successfully make an alpha converter. Well, I have to admit that hunting bug is more difficult than coding it self. OK, now the technical question: Code: #include <iostream>
#include <string>
using namespace std;
int main() {
string c = "af.mpp";
char *b = new char[100];
b = NULL;
b = "mp3";
cout << b;
}
Code: void do_ogg() {
if( fork() == 0 ) {
int child;
arg_list[0] = "oggdec";
song.copy( arg_list[1], songlength, 0 );
arg_list[1][songlength] = '\0';
arg_list[2] = NULL;
spawn( "oggdec", arg_list );
wait(&child);
arg_list[0] = "lame";
outputsong += ".wav";
outputsong.copy( arg_list[1], outputsonglength+4, 0 );
arg_list[1][outputsonglength+4] = '\0';
outputsong = outputsong.substr( 0, outputsonglength );
arg_list[2] = NULL;
spawn( "lame", arg_list );
wait(&child);
arg_list[0] = "rm";
spawn( "rm", arg_list );
wait(&child);
//Look over here:
delete arg_list[2];
arg_list[2] = new char[100];
//Without two lines above, the third operations
//, that is mv blablabla.wav.mp3 blablabla.mp3
// won't work...............
arg_list[0] = "mv";
string temp = outputsong + ".wav" + ".mp3";
temp.copy( arg_list[1], outputsonglength+8, 0 );
arg_list[1][outputsonglength+8] = '\0';
outputsong += ".mp3";
outputsong.copy( arg_list[2], outputsonglength+4, 0 );
arg_list[2][outputsonglength+4] = '\0';
arg_list[3] = NULL;
spawn( "mv", arg_list );
wait(&child);
_exit( 0 );
}
}
Second question: What is the simplest way to debug child process? I have to hack my code. I use combination set follow-fork-mode child, but that does not always work. I have to comment some code to make it work. I would big thank you if you give me a simple explanation how to debug child process ( fork() stuff ) in gdb session ?
__________________ A man asked, "Who are you?" Buddha answered, "I am awaked." |
| gandalf_bar is offline | |
| | #4 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,680
| You're sure making a mess of memory allocation > Look the code above. It works properly. Maybe so, but for none of the reasons I suspect you know about. Lets dissect. char *b = new char[100]; Ok so far, b now points to 100 chars b = NULL; Ohh, bad news, you just lost the memory and you now have a memory leak. b = "mp3"; This points to a string constant (which is not the same as making a copy) Consider this Code: char *b = new char[100]; // allocate an array
strcpy( b, "mp3" ); // b = "mp3" is a memory leak,
// you can still output b, but you'll get problems at the delete
cout << b;
delete [] b; // delete an array
By not making it a process at all. Make sure it works properly as inline code (and ignore the fact that your app stops for a minute). When you're sure it all works, THEN add the single line of code which calls fork() to create a child process. |
| Salem is offline | |
| | #5 |
| Registered User Join Date: Oct 2003
Posts: 92
| OK, my program works great but only can convert one file per operation. so I want to expanded so that my program be able to convert all files in one directory ( if my user choose to input directory not file. ) . Now, assume he choose to convert all ogg files to mp3 files in directory blablabla. So my program will read all files with this code: Code: DIR *d;
struct dirent *dir;
d = opendir(".");
int amount_ogg_files = 0;
if (d)
{
while ((dir = readdir(d)))
{
//count it
if( dir->d_name == oggfiles() ) amount_ogg_files++;
}
closedir(d);
//Ok now I know how many ogg files in this directory
string *the_names_of_ogg_files;
the_names_of_ogg_files = new string[amount_og];
//Read the files again,
d = opendir(".");
if (d)
{
while ((dir = readdir(d)))
{
//Here's I will pass d->d_name to the_names_of_ogg_files
}
closedir(d);
}
Second: You see: Code: string* b; b = new string[amount_of_ogg_files]; Code: char **s; s = new char*[amount_of_ogg_files]; The last one: My user is a crazy guy. He make a directory named like this: blabla.ogg in music directory. He want to convert all ogg files in music directory to mp3 files but there is a directory named blabla.ogg!!!!! How can I test if this is a directory or file?
__________________ A man asked, "Who are you?" Buddha answered, "I am awaked." |
| gandalf_bar is offline | |
| | #6 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,680
| > Is there anyway I can avoid read the files twice? Yeah, use a vector, then you don't have to allocate memory yourself. Vectors can expand themselves Code: vector <string> ogg_files; Use the stat() function. One of the bits in the mode field indicates directory Code: struct stat sbuf;
stat( d->d_name, &sbuf );
if ( S_ISREG(sbuf.st_mode) ) {
// regular file, process it
}
|
| Salem is offline | |
| | #7 |
| Registered User Join Date: Oct 2003
Posts: 92
| Right now, I am so stuck. I don't know what to do now..... Ok I give you the code first. I made some variables to be global because simplify purpose. So don't say global variables are not safe. First, make it work. Then improve it. Bruce Eckel said that. After my program works, I will remove the global variables. My implementation file is window1.cc. And the global variables are: Code: string song, outputsong, s1; int songlength, outputsonglength; char* arg_list[10]; const int file = 1; const int directory = 2; Code: int spawn( char* program, char** arg_list ) {
pid_t child_pid;
child_pid = fork();
if( child_pid != 0 )
return child_pid;
else {
execvp( program, arg_list );
}
}
Code: void do_ogg() {
if( fork() == 0 ) {
int child;
arg_list[0] = "oggdec";
song.copy( arg_list[1], songlength, 0 );
arg_list[1][songlength] = '\0';
arg_list[2] = NULL;
spawn( "oggdec", arg_list );
wait(&child);
arg_list[0] = "lame";
outputsong += ".wav";
outputsong.copy( arg_list[1], outputsonglength+4, 0 );
arg_list[1][outputsonglength+4] = '\0';
outputsong = outputsong.substr( 0, outputsonglength );
arg_list[2] = NULL;
spawn( "lame", arg_list );
wait(&child);
arg_list[0] = "rm";
spawn( "rm", arg_list );
wait(&child);
delete arg_list[2];
arg_list[2] = new char[100];
arg_list[0] = "mv";
string temp = outputsong + ".wav" + ".mp3";
temp.copy( arg_list[1], outputsonglength+8, 0 );
arg_list[1][outputsonglength+8] = '\0';
outputsong += ".mp3";
outputsong.copy( arg_list[2], outputsonglength+4, 0 );
arg_list[2][outputsonglength+4] = '\0';
arg_list[3] = NULL;
spawn( "mv", arg_list );
wait(&child);
_exit( 0 );
}
}
void do_mp3() {
if( fork() == 0 ) {
int child;
arg_list[0] = "mpg321";
song.copy( arg_list[1], songlength, 0 );
arg_list[1][songlength] = '\0';
arg_list[2] = "-w";
outputsong.copy( arg_list[3], outputsonglength, 0 );
arg_list[3][outputsonglength] = '\0';
arg_list[4] = NULL;
spawn("mpg321", arg_list);
wait(&child);
arg_list[0] = "oggenc";
outputsong.copy( arg_list[1], outputsonglength, 0 );
arg_list[1][outputsonglength] = '\0';
arg_list[2] = NULL;
spawn("oggenc", arg_list);
wait(&child);
arg_list[0] = "rm";
outputsong.copy( arg_list[1], outputsonglength, 0 );
spawn("rm", arg_list);
wait(&child);
_exit( 0 );
}
}
Code: void window1::on_processing() {
const int mp3 = 1, ogg = 2, no = 0;
for(int ii=0; ii<10; ii++)
arg_list[ii] = new char[100];
int type;
songlength = song.length();
string temp( song, 0, songlength-4 );
outputsong = temp;
outputsonglength = outputsong.length();
s1 = song.substr(outputsonglength+1,3) ;
if(s1=="mp3") type = mp3;
else if(s1=="ogg") type = ogg;
else type = no;
switch(type) {
case mp3: do_mp3();
break;
case ogg: do_ogg();
break;
default:
break;
}
for(int i=0; i<10; i++)
delete arg_list[i] ;
}
Code: void window1::on_convert_clicked()
{
if(status==1) {
song = input->get_text();
on_processing();
}
else if(status==2) {
Gtk::Dialog *dialog;
dialog = new class Gtk::Dialog("bla bla", *this ) ;
dialog->add_button("ogg",1);
dialog->add_button("mp3",2);
int bla = 1;
bla = dialog->run();
DIR *d;
struct dirent *dir;
delete dialog;
Glib::ustring Direct = input->get_text();
d = opendir(Direct.c_str());
vector<string> files;
string temp;
switch(bla) {
case 1:
if(d) {
while((dir = readdir(d))) {
temp = dir->d_name;
if(temp.length()>=4)
if(temp.substr(temp.length()-4,4)==".ogg")
files.push_back(temp);
}
}
break;
case 2:
if(d) {
while((dir = readdir(d))) {
temp = dir->d_name;
if(temp.length()>=4)
if(temp.substr(temp.length()-4,4)==".mp3")
files.push_back(temp);
}
}
break;
default:
break;
}
int child;
//Look over here, guyZ!!! Here's the part that make trouble
if(fork()==0)
for( int i=0; i<files.size(); i++ ) {
song = Direct + "/" + files[i] ;
on_processing();
wait(&child);
}
//The end of comment
}
}
The program 'converter' received an X Window System error. This probably reflects a bug in the program. The error was 'BadWindow (invalid Window parameter)'. (Details: serial 4528 error_code 3 request_code 10 minor_code 0) (Note to programmers: normally, X errors are reported asynchronously; that is, you will receive the error a while after causing it. To debug your program, run it with the --sync command line option to change this behavior. You can then get a meaningful backtrace from your debugger if you break on the gdk_x_error() function.) I have debug it and it crash misteriously after fork() session in on_convert_clicked() function. After fork() session, it step, step, step, step, then crash. If I post my gdb sessions, it would make my post longer than needed. Again, I got no clue in my gdb session. Maybe this is not correct forum to ask like gtkmm library spesific question but a guy in gtkmm mailing list told me that: I've not looked at your code in any great depth, but I suspect thaton_processing() is trying to talk to the GUI. If this is the case, thenwhen you fork() and it tries to talk to the GUI from one of the childprocesses, you're asking for trouble, as you end up with X windowsshared across processes which X doesn't think they should be accessedfrom, and it starts complaining about it. Try doing everything in asingle process; if it works, then you need to consider more carefullyhow you're going to do things in the background, if you're going to doit - if you do fork(), make sure only the parent talks directly to theGUI. If you need to pass data from the children for the GUI to display,it will have to pass through the parent process in some way - pipes,FIFOs, shared memory, whatever.Hopefully that will help and I'm not barking up entirely the wrong tree. As you can see, guyz, none my child processes talk to GUI....... I reply his email and he said he cann't help further. So I come back into this forum because this error relate with child processes. I found this clue because if in on_convert_clicked() function, I comment these statements: Code: .......................
default:
break;
}
int child;
/*
if(fork()==0)
for( int i=0; i<files.size(); i++ ) {
song = Direct + "/" + files[i] ;
on_processing();
wait(&child);
}
*/
}
..........................
Code: ..................
else type = no;
switch(type) {
case mp3: // do_mp3();
break;
case ogg: // do_ogg();
break;
default:
break;
}
for(int i=0; i<10; i++)
............
Code: ....................
int child;
if(fork()==0)
for( int i=0; i<files.size(); i++ ) {
song = Direct + "/" + files[i] ;
on_processing();
wait(&child);
}
.....................
Note to Salem: Thanx for the previous post. I really almost cann't believe that you reply my previous post in less than 5 minutes!!!! What a wonderful forum and Guru!!!! Note to administrator: I found bug. Try to use blablabla[-i] in [-code] [/-code] block and below it outside [-code] [/-code] you make this block: [-i] [/-i]. It will make italic from [-i] inside [-code] [/-code] block until found [/-i] outside [-code][/-code] block. You will see what I mean. To solve it manually I have to make it blablabla[-i] [-i] [/-i] statement. Use [-i] in [-code] [/-code] block suppose not to make it italic, right?!!! I mean [-i] in [-code] [/-code] block should has no effect, rigth!!!!!
__________________ A man asked, "Who are you?" Buddha answered, "I am awaked." |
| gandalf_bar is offline | |
| | #8 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,680
| Consider using spaces instead of tabs for indenting your code. Code gets indented rather too much when you have half a dozen tabs. > for(int ii=0; ii<10; ii++) arg_list[ii] = new char[100]; Ok so far > arg_list[0] = "mpg321"; Nooooooo You've just lost your allocated memory, and something is going to be badly upset when you try and delete this pointer Use a string copy function strcpy( arg_list[0], "mpg321" ); > for(int i=0; i<10; i++) delete arg_list [i] ; Should be delete [] arg_list [i]; If you new an array, you must delete an array > Note to administrator: PM this to webmaster, or post it on the "Bugs" message at the top of the General Discussion forum |
| Salem is offline | |
| | #9 |
| Registered User Join Date: Oct 2003
Posts: 92
| >Consider using spaces instead of tabs for indenting your code. Code gets indented >rather too much when you have half a dozen tabs. I don't use TAB because Vim already does it for me..... >strcpy( arg_list[0], "mpg321" ); Ok I will use this from now. I think arg_list[0] = "mpg321" is ok as long as this pointer does not deal with NULL. >Should be delete [] arg_list [i] ; Uppss, I forgot it...... Salem or anyone, you got to explain this to me because I finally find bug in my program. Consider this code: Code: ....................
int child;
if(fork()==0)
for( int i=0; i<files.size(); i++ ) {
song = Direct + "/" + files [i] ;
on_processing();
wait(&child);
char *blar[] = {
"ls",
NULL
}
execvp("ls",blar);
}
.....................
Code: char *blar[] = {
"ls",
NULL
}
execvp("ls",blar);
I am so happy. My days are brighter now.... HO HO HO.... ![]() Thank you.....
__________________ A man asked, "Who are you?" Buddha answered, "I am awaked." |
| gandalf_bar is offline | |
| | #10 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,680
| > I don't use TAB because Vim already does it for me..... Then set it to use 4 spaces, not one TAB character. Whether you physically press the tab key is irrelevant, there are tab chars in your code, and it looks a mess posted here. > I think arg_list[0] = "mpg321" is ok as long as this pointer does not deal with NULL. Wrong - you can only delete what you got with new Since "mpg321" isn't from new, then delete will likely barf all over you. I suggest you use opendir() readdir() closedir() for getting directory listings. Hard to say what is wrong with your two examples, since neither compiles, and its too short to guess the context in which they're being used. In any event, you should really specify the full path to the name of the program being run "/bin/ls" instead of just "ls" |
| Salem is offline | |
| | #11 |
| Registered User Join Date: Oct 2003
Posts: 92
| >In any event, you should really specify the full path to the name of the program being >run "/bin/ls" instead of just "ls" I learn about system call from http://www.advancedlinuxprogramming.com . Here's why I choose not to specify the full path of the program. ..................... The exec functions replace the program running in a process with another program. When a program calls an exec function, that process immediately ceases executing that program and begins executing a new program from the beginning, assuming that the exec call doesn't encounter an error. Within the exec family, there are functions that vary slightly in their capabilities and how they are called. 1 Functions that contain the letter p in their names (execvp and execlp) accept a program name and search for a program by that name in the current execution path; functions that don't contain the p must be given the full path of the pro- gram to be executed. 2 Functions that contain the letter v in their names (execv, execvp, and execve) accept the argument list for the new program as a NULL-terminated array of pointers to strings. Functions that contain the letter l (execl, execlp, and execle) accept the argument list using the C language's varargs mechanism. 3 Functions that contain the letter e in their names (execve and execle) accept an additional argument, an array of environment variables.The argument should be a NULL-terminated array of pointers to character strings. Each character string should be of the form "VARIABLE=value". Because exec replaces the calling program with another one, it never returns unless an error occurs. The argument list passed to the program is analogous to the command-line argu- ments that you specify to a program when you run it from the shell.They are available hrough the argc and argv parameters to main. Remember, when a program is nvoked from the shell, the shell sets the first element of the argument list argv[0]) to he name of the program, the second element of the argument list (argv[1]) to the irst command-line argument, and so on.When you use an exec function in your pro- grams, you, too, should pass the name of the function as the first element of the argu- ment list. ...................... What do you think about that? It said if I use execvp that use 'p' character, I don't need to specify the full path of the program I use. Beside that I accept your suggestion fully.
__________________ A man asked, "Who are you?" Buddha answered, "I am awaked." |
| gandalf_bar is offline | |
| | #12 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,680
| Probably doesn't matter for your program. But if your program was a system level program, running as root (say through setuid), it would be trivial for an attacker to change the PATH to something which would invoke an ls which you didn't expect. |
| Salem is offline | |
| | #13 | |
| Registered User Join Date: Oct 2003
Posts: 92
| Quote:
__________________ A man asked, "Who are you?" Buddha answered, "I am awaked." | |
| gandalf_bar is offline | |
| | #14 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,680
| You either - search the path yourself to verify the program you find is the one you expected to find - don't run such programs with extra privileges (you wouldn't normally anyway) If the program calling exec() is already at a high privilege, then it should work extra hard to ensure the program it expects to run is the program it actually runs. |
| Salem is offline | |
| | #15 |
| Registered User Join Date: Oct 2003
Posts: 92
| Hey, Salem, I guess I know why bug happens in my program. Look at this code in the member function of the GUI: Code:
void on_convert_clicked() {
Convert lime;
if(status==1) {
if(fork()==0) {
lime.setSong(input->get_text());
lime.on_processing();
char *arg[] = {
"/bin/ls",
".....",
NULL
};
execvp("/bin/ls",arg);
}
}
else {
}
//Without execvp("/bin/ls",arg); the child process will execute this as long with
// parent process
int stupid = 1;
..................................
}
Code: execvp("/bin/ls",arg);
Code: int stupid = 1; Is that right, Salem???? Just want to ask your confirmation. So I have to put execvp("/bin/ls",arg); so that child process will end after execute this function. Of course I can change execvp to return 0; What do you think, Salem or anyone???? Thank you......
__________________ A man asked, "Who are you?" Buddha answered, "I am awaked." |
| gandalf_bar is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Running Program Problem | warfang | C++ Programming | 10 | 03-28-2007 02:02 PM |
| simple login program problem | suckss | C Programming | 11 | 11-11-2006 05:02 PM |
| Problem with a simple program | Salgat | C Programming | 10 | 06-15-2006 05:57 PM |
| airport Log program using 3D linked List : problem reading from file | gemini_shooter | C Programming | 3 | 03-04-2005 02:46 PM |
| fopen(); | GanglyLamb | C Programming | 8 | 11-03-2002 12:39 PM |