tags:

views:

286

answers:

4

I am trying to debug an issue in my code. I have a process A which runs continuously till I ask it to stop.

Inside A I do the following:

  • mount partition /dev/sda1
  • open() // creates an empty file X
  • write() // write some bytes to it
  • close() // close the file
  • processFile() // Perform some operation
  • remove() // remove file
  • umount /dev/sda1

Note I test after each operation above if it was successful or not befor moving forward. When I do lsof | grep A it shows the file handle of X being owned by process A. I also see it has a (deleted). This prevents me from umounting the partition. Why is this happening and how can I get around this issue?

EDIT: Thanks all. Here is the snippet of the code:

tarFileDesc = _pSysCall->open("test.tar", O_CREAT | O_RDWR | O_APPEND, 0777);    
 if (0 > tarFileDesc)
  return false;

 ... some logging here

 // Write http stream to tar file, istr is an argument to my function     
 int read_buffer_size = 0;     
 buffer = new char[4096];     
 while (!istr.eof() && count < content_length)
 {      
    if ((content_length - count) >= 4096)
     read_buffer_size = 4096;
    else
     read_buffer_size = content_length - count;

    memset(buffer, 0, 4096);
    istr.read(buffer, read_buffer_size);
    std::streamsize in_bytes = istr.gcount();
    if (istr.fail() || istr.bad())
    {
     status = false;
     break;
    }

    if (write(tarFileDesc, buffer, in_bytes) != in_bytes)
    {
     status = false;
     break;
    }
    count += in_bytes;
}
// Cleanup buffer
delete[] buffer;

if ((0 > tarFileDesc) && (0 != close(tarFileDesc)))
    return false;  

if (0 != system("tar C /test -xvf test.tar"))
    return false;

if (0 != remove("test.tar"))
      return false;

Note I even tried just doing the open, close and remove. But I still see the handle being held by process.

A: 

You'll probably have to post some code. But here's a great trick for you - if you create a temporary file in Unix/Linux/Mac OS X, you can delete it IMMEDIATELY and you can still write to it, read it, etc, but as soon as you close it it will go away. It will also go away if some error kills your program before you get around to closing it.

Paul Tomblin
+1  A: 

Thanks all. Here is the snippet of the code:

tarFileDesc = _pSysCall->open("test.tar", O_CREAT | O_RDWR | O_APPEND, 0777);    
 if (0 > tarFileDesc)
  return false;

 ... some logging here

 // Write http stream to tar file, istr is an argument to my function     
 int read_buffer_size = 0;     
 buffer = new char[4096];     
 while (!istr.eof() && count < content_length)
 {      
    if ((content_length - count) >= 4096)
     read_buffer_size = 4096;
    else
     read_buffer_size = content_length - count;

    memset(buffer, 0, 4096);
    istr.read(buffer, read_buffer_size);
    std::streamsize in_bytes = istr.gcount();
    if (istr.fail() || istr.bad())
    {
     status = false;
     break;
    }

    if (write(tarFileDesc, buffer, in_bytes) != in_bytes)
    {
     status = false;
     break;
    }
    count += in_bytes;
}
// Cleanup buffer
delete[] buffer;

if ((0 > tarFileDesc) && (0 != close(tarFileDesc)))
    return false;  

if (0 != system("tar C /test -xvf test.tar"))
    return false;

if (0 != remove("test.tar"))
      return false;

Note I even tried just doing the open, close and remove. But I still see the handle being held by process.

Vtirum
Please edit the question instead of adding an answer
Hasturkun
i'm not sure he can with his reputation?
Matt Joiner
To the OP ... you can delete this comment now; I've put this code in the original question.
Chris J
+5  A: 

The issue lies in these lines:

if ((0 > tarFileDesc) && (0 != close(tarFileDesc)))
    return false;

This will only close the file descriptor if tarFileDesc < 0. What you mean is if tarFileDesc >= 0 then close it as it's a valid file descriptor, so try changing this code to:

if ((0 > tarFileDesc) || (0 != close(tarFileDesc)))
    return false;

This way you return false if the file descriptor is invalid, otherwise you return false if you're unable to close it.

Matt Joiner
HA! That's what you get when you twist expressions to do a compiler warning's job. :-D
DevSolar
Oh, and it's absolutely the right answer of course.
DevSolar
A: 

This look suspicious:

if ((0 > tarFileDesc) && (0 != close(tarFileDesc)))
    return false;

Looking towards the top of your code, you already do a check for 0 > tarFileDesc, and if true return false right at that point. So I'm thinking that this part of the check is redundant? i.e., should this simply read:

if (0 != close(tarFileDesc)))
    return false;
Chris J
Close... see Anacrolix' answer.
DevSolar
@DevSolar -- disagree; the check is still redundant. Why is it needed when the chek for tarFileDesc has already been performed and the function exited?
Chris J
a good point Chris J, however the OP is using a C cleanup paradigm where he means mostly to check and uninitialize at the end of the function. if he was to change the function later the check for a valid file descriptor could again be needed. if anything i'd put it down to an oversight on the OP's part. the first check that the file descriptor is invalid should instead goto the cleanup section instead of returning.
Matt Joiner
@ Chris: You correctly remove the check, but for the wrong reason: Not redundancy was the OP's problem, but a wrongly written check.
DevSolar