ten_druhy
ten_druhy

Reputation: 23

write() prints in wrong order

I'm trying to output ordered set of lines created by multiple processes.

I found that printf() and fprintf() is not suitable for such task. Right now I'm using this set of commands:

sprintf(buff,"%d: some string", (*counter)++); //build string (write can't do that)
write(file, buff, strlen(buff));
memset(buff, 0, strlen(buff)); //clear buffer before next writing

File opening and starting processes is shown below:

int file;
int main(){
    pid_t busPID, riderPID;
    file = open("outputFile.txt", O_WRONLY | O_CREAT | O_APPEND | O_TRUNC, 0666);
    if((busPID = fork()) == 0){
        bus();
    else{
        if((riderPID = fork()) == 0){
            for(int i = 0; i < 10; i++){
                rider();
            }
        }else{
            pid_t waitPID;
            while ((waitPid = wait(&status)) > 0); //wait for all riders to finish
        }
    }
    waitpid(busPID, NULL, 0);
    return 0;
}

Here are functions, which prints output:

void bus() {
    char buff[50];
    //writing
    do {
        //writing
        if(*onStop > 0) {
            //writing
            sem_post(semRider);
            sem_wait(semBus);
            //writing
            *onStop = 0; //internal value, irrelevant for answer
        }
        //writing
        usleep(rand()%busSleep);
        //writing
        sem_post(semRider);
        sem_wait(semBus);
        departuredAkt += temp; //internal value, irrelevant for answer
    } while(departuredAkt < departuredTotal);
    //writing
    exit(EXIT_SUCCESS); //exit this process
}

void rider() {
    char buff[50];
    //writing
    int pos = ++(*onStop);
    //writing
    sem_wait(semRider);
    //writing
    sem_post(semBus);
    sem_wait(semRider);
    //writing
    sem_post(semBus);
    exit(EXIT_SUCCESS);
}

There is only 1 process using bus() function and N processes using rider()function (specified by argument). desired output is:

1: bus string
2: bus string
3: bus string
4: rider 1 string
5: rider 1 string
.
.
.
25: rider N string
26: bus string

My current output looks like this:

1: bus string
2: bus string
3: bus string
4: rider 1 string
6: bus string //here is the problem
5: rider 1 string

Question is, how can I achieve printing lines in correct order?

Upvotes: 0

Views: 156

Answers (1)

Askar Safin
Askar Safin

Reputation: 81

First of all, side note: never use sprintf, this function is completely unsecure. Use snprintf. Example:

snprintf (buff, sizeof (buff), "%d: some string", (*counter)++);

Second: you missed information we need to understand your question. I mean the following information:

  • How exactly you opened file?
  • How you started you processes?
  • Are this processes really processes or they are threads?
  • Did you open file in one process and somehow shared this opened file with other processes or did you opened the file in each process separately?

This details are critical for understanding your question.

Next time you will writing some question, please, provide FULL EXAMPLE. I. e. minimal working example we can compile and run. It should include all relevant details, i. e. starting processes, opening files, etc. And, of course, you should strip all unnecessary details.

Okey, there is two different notion in POSIX: "file descripTOR" and "file descripTION". Websearch for them. Type "man 2 open" in UNIX shell and read carefully, this manual page talks about distinction.

Exact details about how you started your processes and how you opened your file causes (or not causes) sharing of file description between processes and thus affects behavior of "write".

I wrote big text about file descriptors and descriptions. I put it here: https://zerobin.net/?eb2d99ee02f36b92#hQY7vTMCD9ekThAod+bmjlJgnlBxyDSXCYcgmjVSu2w= , because it is not much relevant to this question, but still will be useful for education.

Okey, what to do?

Well, if you for whatever reason cannot share ONE file DESCRIPTION, then simply open file with O_APPEND. :) You don't need to open the file every time you write to it. Simply open it with O_APPEND one time in each process and all will be OK.

Upvotes: 1

Related Questions