yazan yazan - 3 months ago 18
Bash Question

C++ function running twice but only called once

I am learning C++ [Java background fwiw] and trying to write a UNIX shell as a project. I am running into a funny little problem with tokenizing the input for execution. The tok function is getting called twice and I'm not sure why. My current test code is the following:

#include <iostream>
#include <vector>
#include <sstream>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>

using namespace std;

void tok(string, char**);

int main(){
const char* EXIT = "exit";

string input;

cout << "shell>> ";
getline(cin, input);

pid_t pid = fork();

char* args[64]; //arbitrary size, 64 possible whitespace-delimited tokens in command
tok(input, args);
return 0;
}

//copied from http://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
void tok(string inStr, char** args){
int last = 0, next = 0, i = 0;
while( (next = inStr.find(' ', last)) != -1){
cout << i++ << ": " << inStr.substr(last, next-last) << endl;
*args++ = strdup(inStr.substr(last, next-last).c_str());
last = next + 1;
}
cout << i++ << ": " << inStr.substr(last) << endl;
*args++ = strdup(inStr.substr(last).c_str());
*args = '\0';
cout << "done tokenizing..." << endl;
}


My output when I actually run the program is:

$ ./a.out
shell>> ls -l
0: ls
1: -l
done tokenizing...
0: ls
1: -l
done tokenizing...


I'm not sure why it would do that. Can anyone guide me in the right direction please? Thank you

Answer

When you call fork, you create two processes. Each process has nearly the exact same state except for the respective pid_t you receive. If that value is greater than 0, then you are in the parent process (main), and otherwise you are in the child (or fork failed).

Without performing a check on the returned pid_t, both processes will call tok, resulting in the double call behavior you witnessed.

Hide the call behind a check on pid like so:

pid_t pid = fork();
if (pid > 0) // have parent process call tok
{
   char* args[64]; //arbitrary size, 64 possible whitespace-delimited tokens in command
   tok(input, args);
}

To see what else parent and child processes have in common (or not): check the docs

Comments