Re: ftell Issue or Feature

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jun 8, 2011 at 8:09 AM, Christian Grobmeier <grobmeier@xxxxxxxxx>wrote:

> Hello,
>
> I am one of the log4php [1] hackers over at the ASF. We (thats Ivan
> Habunek and myself) have now a nasty issue for which we would be glad
> about input.
>
> Use case:
> Once the log file got a specific size, it will be rolled over. In
> other terms, the big logfile gets closed and a new one is opened. This
> is supposed to work in a multithreaded environment of course. The user
> now claims about multiple creations of small logfiles.
>
> Code [2]:
>
> if(ftell($this->fp) > $this->getMaxFileSize()) {
>        if(flock($this->fp, LOCK_EX)) {
>                if(ftell($this->fp) > $this->getMaxFileSize()) {
>                        $this->rollOver();
>                }
>        }
> }
>
> This is the rollover code. We check with ftell, were the latest
> position is and if it is to big, we try to get a lock. If it is to big
> after we have the lock, we roll it over.
>
> Here mulitiple threads can reach the flock position- then they all
> wait until they get the lock of this file. If it has been rolled by a
> previous thread, they should have got an updated reference to
> $this->fp and skip the rolling.
>
> So, Ivan found out that in the case, we do the second ftell we do not
> get updated positions when another thread has written into the file.
> The object itself is always the same, for all threads. Every thread
> gets this "Appender" from a kind of a pool.
>
> My guess is, every thread gets some kind of a copy of this object,
> working at it. Once it reaches the method, its members states are not
> reflected into the other stack call.
>
> Docs don't tell me anything for my case. I would be really glad about
> suggestions, help, links whatever.


Assuming each thread has its own copy of $this->fp, even after renaming the
log file all other threads will still be pointing at the old file. The
resource is connected to the inode, not the filename, so even if the
filename changes the inode does not, therefore the actual location on disk
represented by the resource does not.

I would fix this by doing the following after acquiring the lock...

1. Close the file
2. Reopen the file
3. Seek to the end
4. Then do the ftell

Alternatively it could just do a filesize on the filename to get the current
size rather than using ftell on the resource. If the size is less than ftell
then another thread has rolled it over and this thread needs to close and
reopen the file. If they match, roll the file over.

-Stuart

-- 
Stuart Dallas
3ft9 Ltd
http://3ft9.com/

[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux