Skip Menu |

This queue is for tickets about the MP3-Tag CPAN distribution.

Report information
The Basics
Id: 66768
Status: open
Priority: 0/
Queue: MP3-Tag

People
Owner: Nobody in particular
Requestors: jagerman [...] jagerman.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Broken temp file generation in MP3::Tag::ID3v2
Date: Tue, 22 Mar 2011 01:16:12 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
MP3::Tag::ID3v2 uses an unsafe tempfile generation, which has the potential to corrupt files if multiple processes using MP3::Tag::ID3v2 are operating on files in the same directory at the same time. I ran into this, with a parallel-processing script, and it clobbered some of my MP3 files. This is just a basic race condition: the file might exist between the time -e is called and the subsequent open(). Rather than trying to fix the tempfile name generation, it would be easier to simply use File::Temp, which is designed to do exactly this sort of thing safely. The attached patch to ID3v2.pm fixes the problem by doing exactly that: it removes the current tempfile generation code, instead using File::Temp's tempfile() to create the file, which should solve the problem.

Message body is not shown because sender requested not to inline it.

Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Tue, 22 Mar 2011 01:48:14 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
I just noticed my first patch was broken: it wasn't actually importing tempfile() from File::Temp. This one contains the import, and I've tested that it actually works. On 22-Mar-11 1:16 AM, Bugs in MP3-Tag via RT wrote: Show quoted text
> > Greetings, > > This message has been automatically generated in response to the > creation of a trouble ticket regarding: > "Broken temp file generation in MP3::Tag::ID3v2", > a summary of which appears below. > > There is no need to reply to this message right now. Your ticket has been > assigned an ID of [rt.cpan.org #66768]. Your ticket is accessible > on the web at: > > https://rt.cpan.org/Ticket/Display.html?id=66768 > > Please include the string: > > [rt.cpan.org #66768] > > in the subject line of all future correspondence about this issue. To do so, > you may reply to this message. > > Thank you, > bug-MP3-Tag@rt.cpan.org > > ------------------------------------------------------------------------- > MP3::Tag::ID3v2 uses an unsafe tempfile generation, which has the > potential to corrupt files if multiple processes using MP3::Tag::ID3v2 > are operating on files in the same directory at the same time. I ran > into this, with a parallel-processing script, and it clobbered some of > my MP3 files. > > This is just a basic race condition: the file might exist between the > time -e is called and the subsequent open(). Rather than trying to fix > the tempfile name generation, it would be easier to simply use > File::Temp, which is designed to do exactly this sort of thing safely. > > The attached patch to ID3v2.pm fixes the problem by doing exactly that: > it removes the current tempfile generation code, instead using > File::Temp's tempfile() to create the file, which should solve the problem. >

Message body is not shown because sender requested not to inline it.

CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Tue, 22 Mar 2011 04:19:56 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Tue, Mar 22, 2011 at 01:48:25AM -0400, Jason Rhinelander via RT wrote: Show quoted text
> Queue: MP3-Tag > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=66768 > > > I just noticed my first patch was broken: it wasn't actually importing > tempfile() from File::Temp. This one contains the import, and I've > tested that it actually works.
I won't like to introduce an extra dependency to fix a rare race condition. (Especially taking into account that `use File::Temp' pulls in 29 modules, including overload.pm!) If you are interested, consider some more lightweight solution... Checking... Well, it looks like File::Temp is included even in 5.6.1, so it won't be a problem if it were not so heavy-weight... Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Tue, 22 Mar 2011 11:22:22 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
It does have a few dependencies, but as you pointed out, it is a core module and so doesn't introduce any to MP3::Tag. As an alternative, how would you feel about only loading File::Temp at run-time when a tempfile is needed? That would, at least, mitigate the heaviness most of the time, when the tag can be updated in-place. I've attached a new patch (ID3v2-runtime-file-temp.patch) that works this way. If you don't want to use File::Temp at all, you can reduce the likelihood of the problem occurring by basing the tempfile filename on the filename of the mp3, instead of just its dirname. i.e. for /some/dir/foo.mp3 the tempfile could be named something like /some/dir/foo.mp3.TMP-0.tmp instead of /some/dir/TMPxx0.tmp. That still has a potential race condition, but at least it would only apply when working on the same file, as opposed to just working on two different files in the same directory. Even better still would be to use a random set of characters (e.g. /some/dir/foo.mp3.xB5z.tmp) instead of just an incremented number. I've attached a second patch (ID3v2-no-file-temp.patch) that does this instead of using File::Temp. It's not as safe as using File::Temp, but it should be much, much harder to trigger the race condition this way, and doesn't use any extra modules. Jason On 22-Mar-11 7:20 AM, Ilya Zakharevich via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=66768> > > On Tue, Mar 22, 2011 at 01:48:25AM -0400, Jason Rhinelander via RT wrote:
>> Queue: MP3-Tag >> Ticket<URL: https://rt.cpan.org/Ticket/Display.html?id=66768> >> >> I just noticed my first patch was broken: it wasn't actually importing >> tempfile() from File::Temp. This one contains the import, and I've >> tested that it actually works.
> > I won't like to introduce an extra dependency to fix a rare race > condition. (Especially taking into account that `use File::Temp' > pulls in 29 modules, including overload.pm!) If you are interested, > consider some more lightweight solution... > > Checking... Well, it looks like File::Temp is included even in 5.6.1, > so it won't be a problem if it were not so heavy-weight... > > Ilya >

Message body is not shown because sender requested not to inline it.

Message body is not shown because sender requested not to inline it.

CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Tue, 22 Mar 2011 13:06:47 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Tue, Mar 22, 2011 at 11:22:39AM -0400, Jason Rhinelander via RT wrote: Show quoted text
> If you don't want to use File::Temp at all, you can reduce the > likelihood of the problem occurring by basing the tempfile filename on > the filename of the mp3, instead of just its dirname. i.e. for > /some/dir/foo.mp3 the tempfile could be named something like > /some/dir/foo.mp3.TMP-0.tmp instead of /some/dir/TMPxx0.tmp.
Won't work on some filesystems... I'm well aware of these race conditions; just do not have tuits to find a proper solution... (The best thing is to ask OS to open-only-if-not-exists.) Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Tue, 22 Mar 2011 22:11:41 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 22-Mar-11 4:06 PM, Ilya Zakharevich via RT wrote: Show quoted text
> Won't work on some filesystems... I'm well aware of these race > conditions; just do not have tuits to find a proper solution... (The > best thing is to ask OS to open-only-if-not-exists.)
That, of course, is exactly what File::Temp does, but it takes a fair chunk of code to get this right in a portable manner. The proper solution here is to use File::Temp--trying to duplicate everything it does, especially in dealing with odd systems, hardly seems worth the effort and the added maintenance cost just to avoid depending on a *core* Perl module that, honestly, doesn't have all that many dependencies. The -runtime patch I attached earlier won't even load File::Temp most of the time, avoiding any resource hit in the majority of cases (it only gets loaded if MP3::Tag::ID3v2 needs to rewrite the entire file). We're still talking a relatively small amount of system resources to load File::Temp and its dependencies, and it seems like reducing the loading to when we actually need it is worthwhile as it fixes a serious (i.e. data loss) problem in a known, correct, portable, tested way. I really want to ask that you reconsider the -runtime patch I sent in my last e-mail. Using File::Temp is the standard, accepted, core Perl way of avoiding exactly this problem, and if it's only loaded when rewriting an entire file (on the order of a few MB in typical use cases), the overhead of File::Temp seems worthwhile to avoid data loss. Jason
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Tue, 22 Mar 2011 19:51:31 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Tue, Mar 22, 2011 at 10:11:51PM -0400, Jason Rhinelander via RT wrote: Show quoted text
> That, of course, is exactly what File::Temp does, but it takes a fair > chunk of code to get this right in a portable manner.
I doubt it very much. Show quoted text
> The proper > solution here is to use File::Temp--trying to duplicate everything it > does, especially in dealing with odd systems, hardly seems worth the > effort and the added maintenance cost just to avoid depending on a > *core* Perl module that, honestly, doesn't have all that many > dependencies. The -runtime patch I attached earlier won't even load > File::Temp most of the time, avoiding any resource hit in the majority > of cases (it only gets loaded if MP3::Tag::ID3v2 needs to rewrite the > entire file). We're still talking a relatively small amount of system > resources to load File::Temp and its dependencies, and it seems like > reducing the loading to when we actually need it is worthwhile as it > fixes a serious (i.e. data loss) problem in a known, correct, portable, > tested way.
Using a module which loads overload.pm to open a temporary file cannot be "the proper solution". Yours, Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Wed, 23 Mar 2011 00:19:09 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 22-Mar-11 10:51 PM, Ilya Zakharevich via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=66768> > > On Tue, Mar 22, 2011 at 10:11:51PM -0400, Jason Rhinelander via RT wrote:
>> That, of course, is exactly what File::Temp does, but it takes a fair >> chunk of code to get this right in a portable manner.
> > I doubt it very much.
Look for yourself. vim `perldoc -l File::Temp` Show quoted text
>> The proper >> solution here is to use File::Temp--trying to duplicate everything it >> does, especially in dealing with odd systems, hardly seems worth the >> effort and the added maintenance cost just to avoid depending on a >> *core* Perl module that, honestly, doesn't have all that many >> dependencies. The -runtime patch I attached earlier won't even load >> File::Temp most of the time, avoiding any resource hit in the majority >> of cases (it only gets loaded if MP3::Tag::ID3v2 needs to rewrite the >> entire file). We're still talking a relatively small amount of system >> resources to load File::Temp and its dependencies, and it seems like >> reducing the loading to when we actually need it is worthwhile as it >> fixes a serious (i.e. data loss) problem in a known, correct, portable, >> tested way.
> > Using a module which loads overload.pm to open a temporary file cannot > be "the proper solution".
Why not? Jason
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Wed, 23 Mar 2011 00:34:42 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 22-Mar-11 10:51 PM, Ilya Zakharevich via RT wrote: Show quoted text
> Using a module which loads overload.pm to open a temporary file cannot > be "the proper solution".
I should also point out that the patch I provided doesn't use the object-oriented interface to File::Temp at all, and thus no use of overloading takes place. But the above comment leads me to suspect that your objections at this point are religious rather than logical. You have my patches, which you are free to ignore; I just hope that you include *some* sort of fix for this problem, even if the fix is duplicating half of File::Temp just to avoid allowing overload.pm to be loaded. Yours, Jason Rhinelander
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Wed, 23 Mar 2011 02:38:46 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Wed, Mar 23, 2011 at 12:34:51AM -0400, Jason Rhinelander via RT wrote: Show quoted text
> Queue: MP3-Tag > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=66768 > > > On 22-Mar-11 10:51 PM, Ilya Zakharevich via RT wrote:
> > Using a module which loads overload.pm to open a temporary file cannot > > be "the proper solution".
> > I should also point out that the patch I provided doesn't use the > object-oriented interface to File::Temp at all, and thus no use of > overloading takes place.
Irrelevant. Loading overload.pm already does the damage... Yours, Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Thu, 24 Mar 2011 15:21:06 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 23-Mar-11 5:38 AM, Ilya Zakharevich via RT wrote: Show quoted text
> Irrelevant. Loading overload.pm already does the damage...
I'd like to believe you on this one, but I can't seem to find any documentation or evidence of overload imposing any significant overhead on non-overloaded variables, aside from a broken RedHat patch to Perl about 3 years ago. Moreover my own simple test: time perl -le 'package Foo; use overload ">" => sub {}; package main; for (my $i = 0; $i < 100_000_000; $i++) { print $i if $i % 10_000_000 == 0 }' versus time perl -le 'package Foo; package main; for (my $i = 0; $i < 100_000_000; $i++) { print $i if $i % 10_000_000 == 0 }' doesn't appear to indicate any speed penalty on the code at all. perldoc overload also seems to imply that there is no measurable performance penalty for overload being loaded in another module. So what, exactly, is the damage done by indirectly loading overload?
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Thu, 24 Mar 2011 14:05:08 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Thu, Mar 24, 2011 at 03:21:18PM -0400, Jason Rhinelander via RT wrote: Show quoted text
> On 23-Mar-11 5:38 AM, Ilya Zakharevich via RT wrote:
> > Irrelevant. Loading overload.pm already does the damage...
> > I'd like to believe you on this one, but I can't seem to find any > documentation or evidence of overload imposing any significant overhead > on non-overloaded variables, aside from a broken RedHat patch to Perl > about 3 years ago.
When I implemented overloading for Perl, I, obviously, did a lot of benchmarking. That time superpipelining and cache-coloring-type optimizations in the processors were not widespread, so one could do "pretty predictable" benchmarking. IIRC, the slowdown due to my patch was about +- 1% when overloading was not used (probably due to offset of addresses, so better or worse alignment of cache lines), and "about several percent" (do not remember more precise) when overload was used. On processors of nowadays, benchmarks vary too much to be meaningful without major statistical samples. Yours, Ilya
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Thu, 24 Mar 2011 14:11:19 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Wed, Mar 23, 2011 at 12:19:17AM -0400, Jason Rhinelander via RT wrote: Show quoted text
> >> That, of course, is exactly what File::Temp does, but it takes a fair > >> chunk of code to get this right in a portable manner.
> > > > I doubt it very much.
> > Look for yourself. vim `perldoc -l File::Temp`
Did you? Can you find anything else done except sysopen($fh, $path, $flags, 0600); with $flags being essentially O_CREAT | O_EXCL | O_RDW, and checking for $!{EEXIST} ? Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Thu, 24 Mar 2011 17:27:18 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
While I'm still not convinced that a performance deficit that requires "major statistical samples" to detect, which is only loaded for a small fraction of MP3::Tag's use case, I'm willing to concede the point in order to get this fixed in *some* way. So let me ask this: are you willing to apply some patch on this, and if so, what code is acceptable here? The code from perldoc -q temporary (modified as appropriate, of course--actually, at a quick glance that code appears wrong in that it tests *FH, but actually opens a lexical filehandle $fh)? File::Temp appears to have additional safeness code for systems where the simple sysopen with O_WRONLY|O_EXCL|O_CREAT is insufficient to guarantee safeness, but that code plus a randomly generated sequence (instead of the current counter-from-0 approach) ought to eliminate on POSIX-like systems on non-networked filesystems, and significantly reduce the occurrence otherwise. So in short, I suggest, and will write it and submit a patch, if you concur: - using dirname($filename) . "/TMP" . (random sequence of 5 alphanumeric characters) . ".tmp" for the filename - using sysopen() with O_WRONLY|O_EXCL|O_CREAT instead of open() Does that work? Jason On 24-Mar-11 5:05 PM, Ilya Zakharevich via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=66768> > > On Thu, Mar 24, 2011 at 03:21:18PM -0400, Jason Rhinelander via RT wrote:
>> On 23-Mar-11 5:38 AM, Ilya Zakharevich via RT wrote:
>>> Irrelevant. Loading overload.pm already does the damage...
>> >> I'd like to believe you on this one, but I can't seem to find any >> documentation or evidence of overload imposing any significant overhead >> on non-overloaded variables, aside from a broken RedHat patch to Perl >> about 3 years ago.
> > When I implemented overloading for Perl, I, obviously, did a lot of > benchmarking. That time superpipelining and cache-coloring-type > optimizations in the processors were not widespread, so one could > do "pretty predictable" benchmarking. > > IIRC, the slowdown due to my patch was about +- 1% when overloading > was not used (probably due to offset of addresses, so better or worse > alignment of cache lines), and "about several percent" (do not > remember more precise) when overload was used. > > On processors of nowadays, benchmarks vary too much to be meaningful > without major statistical samples. > > Yours, > Ilya >
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Thu, 24 Mar 2011 17:46:52 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 24-Mar-11 5:11 PM, Ilya Zakharevich via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=66768> > > On Wed, Mar 23, 2011 at 12:19:17AM -0400, Jason Rhinelander via RT wrote:
>>>> That, of course, is exactly what File::Temp does, but it takes a fair >>>> chunk of code to get this right in a portable manner.
>>> >>> I doubt it very much.
>> >> Look for yourself. vim `perldoc -l File::Temp`
> > Did you? Can you find anything else done except > > sysopen($fh, $path, $flags, 0600); > > with $flags being essentially O_CREAT | O_EXCL | O_RDW, and checking > for $!{EEXIST} ?
Each of O_NOFOLLOW, O_BINARY, O_LARGEFILE, O_NOINHERIT, and O_EXLOCK is also set, if they exist. Even still, we don't necessarily get safeness on a network mount, hence my suggestions for a random filename as well instead of a incremental integer value. Show quoted text
> Ilya >
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Thu, 24 Mar 2011 17:49:02 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jason [...] imaginary.ca>
On 24-Mar-11 5:46 PM, Jason Rhinelander wrote: Show quoted text
> On 24-Mar-11 5:11 PM, Ilya Zakharevich via RT wrote:
>> <URL: https://rt.cpan.org/Ticket/Display.html?id=66768> >> >> On Wed, Mar 23, 2011 at 12:19:17AM -0400, Jason Rhinelander via RT wrote:
>>>>> That, of course, is exactly what File::Temp does, but it takes a fair >>>>> chunk of code to get this right in a portable manner.
>>>> >>>> I doubt it very much.
>>> >>> Look for yourself. vim `perldoc -l File::Temp`
>> >> Did you? Can you find anything else done except >> >> sysopen($fh, $path, $flags, 0600); >> >> with $flags being essentially O_CREAT | O_EXCL | O_RDW, and checking >> for $!{EEXIST} ?
> > Each of O_NOFOLLOW, O_BINARY, O_LARGEFILE, O_NOINHERIT, and O_EXLOCK is > also set, if they exist.
... plus a bunch of extra tests if someone increases File::Temp's safe_level.
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Thu, 24 Mar 2011 19:41:31 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Thu, Mar 24, 2011 at 05:49:11PM -0400, Jason Rhinelander via RT wrote: Show quoted text
> >> Did you? Can you find anything else done except > >> > >> sysopen($fh, $path, $flags, 0600); > >> > >> with $flags being essentially O_CREAT | O_EXCL | O_RDW, and checking > >> for $!{EEXIST} ?
> > > > Each of O_NOFOLLOW, O_BINARY, O_LARGEFILE, O_NOINHERIT, and O_EXLOCK is > > also set, if they exist.
This is what "essentially" meant. Do we need any of these flags? Show quoted text
> ... plus a bunch of extra tests if someone increases File::Temp's > safe_level.
Did you increase it in your patch? Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Fri, 25 Mar 2011 03:08:02 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 24-Mar-11 10:42 PM, Ilya Zakharevich via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=66768> > > On Thu, Mar 24, 2011 at 05:49:11PM -0400, Jason Rhinelander via RT wrote:
>>>> Did you? Can you find anything else done except >>>> >>>> sysopen($fh, $path, $flags, 0600); >>>> >>>> with $flags being essentially O_CREAT | O_EXCL | O_RDW, and checking >>>> for $!{EEXIST} ?
>>> >>> Each of O_NOFOLLOW, O_BINARY, O_LARGEFILE, O_NOINHERIT, and O_EXLOCK is >>> also set, if they exist.
> > This is what "essentially" meant. Do we need any of these flags?
I do not know. I would guess "probably" for O_BINARY and O_EXLOCK, and "maybe" for the others. I do, however, assume that the author(s) of File::Temp knows better than I, and so assume that they have some importance on some system somewhere. I've written another patch, addressing the various concerns you have raised in this report thus far. This time using sysopen, as previously discussed, with all the various flags that File::Temp sets. If you know any of these to be obviously unnecessary for the file replacement being done in MP3::Tag::ID3v2, please remove them. Additionally, this patch uses TMPxxxx.tmp for the filename, where xxxxx is replaced with 5 random \w characters (this ought to help when the filesystem is on some mountpoint (e.g. a network mount) where sysopen cannot guarantee safeness of the open). Finally, the patch also attempts to preserve the file permissions of the original file (though forcing 0600 at a minimum). I tested the patch on a few MP3s, completely removing and re-adding the ID3v2 tags to force the file rewriting, and everything appears to be working properly. I specifically, for testing, changed the ID3v2.pm code to use much less random filename generation with several calls in parallel, and verified that the sysopen call, in fact, failing correctly when the file already exists. Hopefully you find this new patch acceptable, and can include it in the next release of MP3::Tag. Thanks, Jason
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Fri, 25 Mar 2011 03:09:09 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
Oops: attaching the patch would help, I suppose. Jason

Message body is not shown because sender requested not to inline it.

CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Fri, 25 Mar 2011 02:41:04 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Fri, Mar 25, 2011 at 03:08:14AM -0400, Jason Rhinelander via RT wrote: Show quoted text
> >>> Each of O_NOFOLLOW, O_BINARY, O_LARGEFILE, O_NOINHERIT, and O_EXLOCK is > >>> also set, if they exist.
Show quoted text
> > This is what "essentially" meant. Do we need any of these flags?
Show quoted text
> I do not know. I would guess "probably" for O_BINARY and O_EXLOCK, and
"Definitely NO" for O_BINARY and O_EXLOCK. Show quoted text
> "maybe" for the others.
The only one which may have some vague relation to real needs is O_LARGEFILE. Unfortunately, I have no clue what it means.... Show quoted text
> I do, however, assume that the author(s) of > File::Temp knows better than I, and so assume that they have some > importance on some system somewhere.
As I said, I do not give ANY trust to authors of File::Temp, judging by how it is designed... Show quoted text
> I've written another patch, addressing the various concerns you have > raised in this report thus far. This time using sysopen, as previously > discussed, with all the various flags that File::Temp sets.
Thanks! I was planning to do this for ages, just did not know how to do it exactly... Your prodding worked well in this regard... Show quoted text
> Additionally, this patch uses TMPxxxx.tmp for the filename, where xxxxx > is replaced with 5 random \w characters (this ought to help when the > filesystem is on some mountpoint (e.g. a network mount) where sysopen > cannot guarantee safeness of the open). Finally, the patch also > attempts to preserve the file permissions of the original file (though > forcing 0600 at a minimum).
I thought about this, and I'm not absolutely sure that it is what a user would want. Maybe one can make it configurable, as other hard-to-decide matters... Yours, Ilya
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Fri, 25 Mar 2011 02:47:18 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Fri, Mar 25, 2011 at 03:09:24AM -0400, Jason Rhinelander via RT wrote: Show quoted text
> Queue: MP3-Tag > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=66768 > > > Oops: attaching the patch would help, I suppose.
Just checking for an obvious bug, and it is there... Show quoted text
> + for (1 .. 1000) { > + my $tempfile = $base . join('', @tempfile_chars[map rand(@tempfile_chars), 1..5]) . '.tmp'; > +
Bits of rand() are intended to be independent. However, there is no guarantie that bits of SEVERAL calls to rand() are independent. One should base things on a result of one call to rand()... Yours, Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Fri, 25 Mar 2011 10:55:12 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 25-Mar-11 5:47 AM, Ilya Zakharevich via RT wrote: Show quoted text
> Just checking for an obvious bug, and it is there... >
>> + for (1 .. 1000) { >> + my $tempfile = $base . join('', @tempfile_chars[map rand(@tempfile_chars), 1..5]) . '.tmp'; >> +
> > Bits of rand() are intended to be independent. However, there is no > guarantie that bits of SEVERAL calls to rand() are independent. One > should base things on a result of one call to rand()...
Since guaranteed independence is not required here, that is not a bug, and you know it. Your hostility, however, tells me that I am wasting my time in attempting to propose a solution to this bug. You have my patches; use bits of them or do something else as you like. Jason
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Fri, 25 Mar 2011 08:05:06 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Fri, Mar 25, 2011 at 10:55:24AM -0400, Jason Rhinelander via RT wrote: Show quoted text
> Queue: MP3-Tag > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=66768 > > > On 25-Mar-11 5:47 AM, Ilya Zakharevich via RT wrote:
> > Just checking for an obvious bug, and it is there... > >
> >> + for (1 .. 1000) { > >> + my $tempfile = $base . join('', @tempfile_chars[map rand(@tempfile_chars), 1..5]) . '.tmp'; > >> +
> > > > Bits of rand() are intended to be independent. However, there is no > > guarantie that bits of SEVERAL calls to rand() are independent. One > > should base things on a result of one call to rand()...
> > Since guaranteed independence is not required here, that is not a bug, > and you know it.
Either you need randomness, and then you try to get some, or you do not - then do not call rand(). Show quoted text
> Your hostility, however, tells me that I am wasting my time in > attempting to propose a solution to this bug. You have my patches; use > bits of them or do something else as you like.
Your hostility makes this conversation moot. A pity, Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Fri, 25 Mar 2011 15:45:25 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 25/03/11 11:05 AM, Ilya Zakharevich via RT wrote: Show quoted text
> Your hostility makes this conversation moot.
I apologize for the tenor of my previous e-mail. I am interested in getting this fixed, as I find the module very useful, and do appreciate the desire to get it fixed correctly. Show quoted text
>>> Bits of rand() are intended to be independent. However, there is no >>> guarantie that bits of SEVERAL calls to rand() are independent. One >>> should base things on a result of one call to rand()...
>> >> Since guaranteed independence is not required here, that is not a bug, >> and you know it.
> > Either you need randomness, and then you try to get some, or you do > not - then do not call rand().
The bigger problem here is that even scooping the bits out of a single rand() call doesn't actually give enough randomness: in particular, if I fork (presuming rand() has been called at least once before the fork(), i.e. so that rand has been seeded), then attempt to operate on two files in the same directory at the same time, the same rand() value (and, for that matter, sequence of rand() values) will be generated--whether or not I use the bits from one rand() call or a sequence of rand() calls. Since this race condition seems most likely to come up in a script that forks and uses MP3::Tag in parallel (I may be biased--but that was how I ran into it), I tend to agree that any use of rand() here--whether 5 rand() calls, or one rand() call divided into 5 sets of bits--isn't actually any more random than the existing 0..999 sequence, and thus isn't solving anything when sysopen can't guarantee non-overwriting properly. I'm not entirely sure what a feasible solution is here. You mentioned earlier that there were portability problems basing the filename on the MP3 filename as I did in one of the earlier patches--could we amend that filename generation in some way to mitigate the problem here? On a separate note, while looking at the code I noticed another potential data loss problem: print values aren't checked, so if writing to the temp MP3 file fails (e.g. because of a full disk), we still clobber the original with a truncated version. If you'd like, I'd be happy to submit a separate patch that checks those, unlinking the tempfile and returning an error value if a print fails. I didn't want to throw it into the previous patch as it really is a separate issue--but the two patches touch some of the same code and would thus be dependent. Jason
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Fri, 25 Mar 2011 17:15:21 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Fri, Mar 25, 2011 at 03:22:24PM -0400, Jason Rhinelander via RT wrote: Show quoted text
> Queue: MP3-Tag > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=66768 > > > On 25/03/11 11:05 AM, Ilya Zakharevich via RT wrote: >
> > Your hostility makes this conversation moot.
> > I apologize for the tenor of my previous e-mail. I am interested in > getting this fixed, as I find the module very useful, and do appreciate > the desire to get it fixed correctly.
I might have been hostile indeed, but I believe not to you, but to people who busted so important a module... What you did is great, and I hope to work on it ASAP (which, unfortunately, may be some wait...). Thanks again, Ilya
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Mon, 28 Mar 2011 04:16:39 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Fri, Mar 25, 2011 at 03:22:24PM -0400, Jason Rhinelander via RT wrote: Show quoted text
> The bigger problem here is that even scooping the bits out of a single > rand() call doesn't actually give enough randomness: in particular, if I > fork (presuming rand() has been called at least once before the fork(), > i.e. so that rand has been seeded), then attempt to operate on two files > in the same directory at the same time, the same rand() value (and, for > that matter, sequence of rand() values) will be generated--whether or > not I use the bits from one rand() call or a sequence of rand() calls.
Untested: my $r = @arr ** 5; # limit # processes may have the same seed if rand() is called before fork() $r = ($$ + int(rand $r)) % $r; # read randomness from ONE call to rand() my $X = join '', map { my $o = $r % @arr; $r = int($r/@arr); chr $o } 1..5; Yours, Ilya
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Mon, 28 Mar 2011 04:19:03 -0700
To: Ilya Zakharevich via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Mon, Mar 28, 2011 at 07:16:49AM -0400, Ilya Zakharevich via RT wrote: Show quoted text
> my $r = @arr ** 5; # limit > # processes may have the same seed if rand() is called before fork() > $r = ($$ + int(rand $r)) % $r; # read randomness from ONE call to rand() > my $X = join '', map { my $o = $r % @arr; $r = int($r/@arr); chr $o } 1..5;
Silly me, forgot to use @arr: my $r = @arr ** 5; # limit # processes may have the same seed if rand() is called before fork() $r = ($$ + int(rand $r)) % $r; # read randomness from ONE call to rand() my $X = join '', map { my $o = $r % @arr; $r = int($r/@arr); $arr[$o] } 1..5; Ilya
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Mon, 28 Mar 2011 05:45:40 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Fri, Mar 25, 2011 at 03:22:24PM -0400, Jason Rhinelander via RT wrote: Show quoted text
> On a separate note, while looking at the code I noticed another > potential data loss problem: print values aren't checked, so if writing > to the temp MP3 file fails (e.g. because of a full disk), we still > clobber the original with a truncated version.
Checking result of print() is not needed. But one MUST check the result of close() indeed! The only excuse I have is that "it is not my code", and I just have not have tuits to handle it... Show quoted text
> If you'd like, I'd be > happy to submit a separate patch that checks those, unlinking the > tempfile and returning an error value if a print fails.
Thanks a lot! However, note that I do not see how returning an error value would be a solution. I suspect one should better die() instead... Thanks, Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Mon, 28 Mar 2011 09:18:46 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
On 28-Mar-11 8:45 AM, Ilya Zakharevich via RT wrote: Show quoted text
> <URL: http://rt.cpan.org/Ticket/Display.html?id=66768> > > On Fri, Mar 25, 2011 at 03:22:24PM -0400, Jason Rhinelander via RT wrote:
>> On a separate note, while looking at the code I noticed another >> potential data loss problem: print values aren't checked, so if writing >> to the temp MP3 file fails (e.g. because of a full disk), we still >> clobber the original with a truncated version.
> > Checking result of print() is not needed. But one MUST check the > result of close() indeed! The only excuse I have is that "it is not > my code", and I just have not have tuits to handle it... >
>> If you'd like, I'd be >> happy to submit a separate patch that checks those, unlinking the >> tempfile and returning an error value if a print fails.
> > Thanks a lot! However, note that I do not see how returning an error > value would be a solution. I suspect one should better die() > instead...
Well, yes, that would be better. I assume, then, that we should also change the other failures (unable to open the temp file, unable to rename it, ...) to die as well? Jason
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Mon, 28 Mar 2011 10:26:49 -0700
To: Jason Rhinelander via RT <bug-MP3-Tag [...] rt.cpan.org>
From: Ilya Zakharevich <nospam-abuse [...] ilyaz.org>
On Mon, Mar 28, 2011 at 09:18:57AM -0400, Jason Rhinelander via RT wrote: Show quoted text
> Well, yes, that would be better. I assume, then, that we should also > change the other failures (unable to open the temp file, unable to > rename it, ...) to die as well?
"Unable to rename it" is tricky: the user who reads error messages has a chance to correct it later. I would make it user-configurable with the default being "be fatal". Hmm, "unable to do something" is ALWAYS correctable later - unless we do something really stupid (like the current practice of overwriting files ;-). So the criterion should better be "is the error expected to persist if we do many files in a loop". "Unable to rename" looks like some file locking issue which MAY be specific to a particular file. The other two errors look like some filesystem problems, and would usually "persist" for other files as well... Just thinking aloud... So maybe "unable to rename it" reserves a special treatment indeed... Ilya
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Wed, 25 May 2011 16:15:07 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
I've been unable to look at this again until now; please find attached my updated patch. Changes from the last version: - Only tries to set O_NOFOLLOW and O_LARGEFILE (if available), no longer trying the various other O_ flags from the previous patch. - Uses a single rand call (incorporating $$) for the temporary filename, as discussed earlier in this thread. - Checks the return of close on the tempfile to make sure writing the file succeeded before we try to clobber the original. The patch still die()s on errors writing/closing/renaming the tempfile. The code, as currently written, doesn't have an obvious (to me) mechanism for returning an error (especially since the involved methods are typically only indirectly called, e.g. when more space is needed). Having a configurable means of not having these treated as die()s is a good idea, but needs a bit more thought, and would probably be better to be MP3::Tag-wide instead of merely specific to MP3::Tag::ID3v2. Jason On 28-Mar-11 1:27 PM, Ilya Zakharevich via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=66768> > > On Mon, Mar 28, 2011 at 09:18:57AM -0400, Jason Rhinelander via RT wrote:
>> Well, yes, that would be better. I assume, then, that we should also >> change the other failures (unable to open the temp file, unable to >> rename it, ...) to die as well?
> > "Unable to rename it" is tricky: the user who reads error messages has > a chance to correct it later. I would make it user-configurable with > the default being "be fatal". > > Hmm, "unable to do something" is ALWAYS correctable later - unless we > do something really stupid (like the current practice of overwriting > files ;-). So the criterion should better be "is the error expected > to persist if we do many files in a loop". > > "Unable to rename" looks like some file locking issue which MAY be > specific to a particular file. The other two errors look like some > filesystem problems, and would usually "persist" for other files as > well... Just thinking aloud... > > So maybe "unable to rename it" reserves a special treatment indeed... > > Ilya >

Message body is not shown because sender requested not to inline it.

Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Wed, 25 May 2011 16:19:22 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
I should also add that I'm driven a little mad by the conflicting tab settings: the file has apparently been edited by people using a mixture of 4-space tabs, 8-space tabs, and pure space indentation, for which no tabstop setting seems to work across the whole file. I tried to keep the tabbing in each area the same so as to avoid unnecessary diff bloat, but reindenting the file in some universal style would be worthwhile. Jason
Subject: Re: [rt.cpan.org #66768] AutoReply: Broken temp file generation in MP3::Tag::ID3v2
Date: Thu, 26 May 2011 17:16:14 -0400
To: bug-MP3-Tag [...] rt.cpan.org
From: Jason Rhinelander <jagerman [...] jagerman.com>
One more update--the previous patch had a (stupid) bug in the mode preservation that was actually mode-clobbering. Jason

Message body is not shown because sender requested not to inline it.