0

I have some C code running on a linux OS into a portable device. I'm using a VRmagic system, similar to BeagleBone etc...).

In this code, I'm using the following function to write results inside a txt file.


//globale definition
FILE *logfile;
const char *logpath = "/MY_DEVICE/log.txt";
const char *main_folder_result_path = "/MEASUREMENT_RESULTS/";
const char *all_measurement_results_file_name = "all_computation_data.txt";

void save_to_log_file(const char *logpath,const char *message){
    #ifdef savealllog
        logfile = fopen(logpath,"a");  //logpath = "/MY_DEVICE/log.txt";
        fprintf(logfile,"%s",message);
        fclose(logfile);
    #endif
    #ifdef printalloutput
        printf("%s",message);
    #endif
}

void append_all_measurement_file(){

    char buff[255];
    char filename[255];

    save_to_log_file(logpath,"     Appending all measurement file...");

    sprintf(filename,"%s%s",main_folder_result_path,all_measurement_results_file_name);

    //here after we create the header if the file does not exist already
    FILE *pFile_all_measurement_results = fopen(filename, "r"); //lets try to read the file
    if (pFile_all_measurement_results == NULL){ // if file does not exist
        pFile_all_measurement_results = fopen(filename, "w");
        fprintf(pFile_all_measurement_results,"date-time S_type Part_name batch count abs value_1 value_2 value_3 value_4\n");
        fclose(pFile_all_measurement_results);
    }
    else{
        fclose(pFile_all_measurement_results); //if file does exist then we have to close it here
    }

    //here after we are going to write results
    pFile_all_measurement_results = fopen(filename, "a"); //lets open the file in append mode

    fprintf(pFile_all_measurement_results,"%s %s %s %d %d %d ",dateandtimetps.dt,measurement_type_str,Name_Str, batch_number,count_number,absolute_measurement_number);
    fprintf(pFile_all_measurement_results,"%.03f ", value_1);
    fprintf(pFile_all_measurement_results,"%.03f ", value_2);
    fprintf(pFile_all_measurement_results,"%.03f ", value_3);
    fprintf(pFile_all_measurement_results,"%.03f\n", value_4); //(there are a bit more in reality.....)

    fclose(pFile_all_measurement_results); //we can now close the file

    save_to_log_file(logpath,"done.\n");
}

99.9% of the time all is OK. But, randomly, I do have some NUL character in my file, and this happen when I turn OFF my system.

Looks like the file has not been closed properly or something like that for some reason.....

When I get my txt file, and open it with notepad++ on my computer, it does look like the following:

NUL line in the file

I can confirm that the device has been turned OFF between line 172 and line 174.

Many thanks for help

phuclv
  • 37,963
  • 15
  • 156
  • 475
Bobby
  • 43
  • 2
  • 2
    "I can confirm that the device has been turned OFF between line 172 and line 174.", very useful without line count... Please do a real [mcve]. "//globale definition" yeah global nothing could go wrong. – Stargateur Dec 07 '17 at 11:05
  • 1
    Is there only ONE process writing to the file? – Paul Ogilvie Dec 07 '17 at 11:10
  • 3
    "I do have some NUL character in my file, and this happen when I turn OFF my system.", why did you expect that when you turn off brutally your system saving file will be OK ? Your code look Ok. When you turn OFF your system brutally, things wrong happen. – Stargateur Dec 07 '17 at 11:12
  • @Stargateur: I mean lines 72 and 74, picture attached to my comment if you click onto "NUL line in the file", link to picture. – Bobby Dec 07 '17 at 12:25
  • @Paul Ogilvie: yes only one – Bobby Dec 07 '17 at 12:25
  • @ Stargateur: I do not turn OFF brutally. I'm using one of the PWRBUTTON input of my device. Using that, the linux system turns off properly. I've assumed so far that it also stops my running process properly. In such a way that all opened stream are closed etc.... so that my output files would be ok, even if, theoritically, I do close the stream with fclose all the time in my algo. – Bobby Dec 07 '17 at 12:36
  • 1
    *I've assumed so far that it also stops my running process properly.* Why would you assume that? You're not even checking the return value from `fprintf()` nor `fclose()`, both of which can fail. And if you have multiple processes writing to the log file, that's another possible source of corruption. – Andrew Henle Dec 07 '17 at 15:09

1 Answers1

2

Just closing a file on Unix systems does not implicate the contents are instantly written to disk; usually buffering/caching is enabled.

To make sure the contents are written you can use sync() immediately after a write and/or close operation, which will minimize the risk of lost updates.

Additionally I recommend to use a journaling filesystem like ext4 (which may not be an option on external drives like USB pens, but is strongly recommend for all system and data partitions). This will not save you from data loss in case of a power failure or crash, but will avoid inconsistencies/partial writes like you are experiencing.

Murphy
  • 3,827
  • 4
  • 21
  • 35
  • OK Murphy many thanks. So I understand that I should have sync(pFile_all_measurement_results); just before using fclose(pFile_all_measurement_results); right ? – Bobby Dec 08 '17 at 12:04
  • The reverse, first close (finish the logical file access) then sync (write all changes to the drive). However you'll have to check whether this really fixes your problem; from the additional comments to your question I conclude that there may be some other issue in the sequence of events that may cause this behaviour. It would be helpful if you could give a **complete and well arranged** account of what's happening, including a [mcve], instead of single pieces of information. – Murphy Dec 08 '17 at 12:15