Boost C++ Libraries: Ticket #1578: bug in readdir_r_simulator() in a multi-threaded environment https://svn.boost.org/trac10/ticket/1578 <p> g++, Boost 1.34.1, <a class="missing wiki">SunOs</a> 5.7, and a multi-threaded environment. </p> <p> This program never ends: </p> <pre class="wiki">#include &lt;boost/filesystem/fstream.hpp&gt; #include &lt;boost/filesystem/operations.hpp&gt; #include &lt;boost/filesystem/convenience.hpp&gt; #include &lt;boost/foreach.hpp&gt; #include &lt;iostream&gt; int main() { namespace fs = boost::filesystem; fs::path path(".",fs::native); if(fs::exists(path) &amp;&amp; fs::is_directory(path)) { fs::directory_iterator begin(path), end; BOOST_FOREACH(fs::path file, std::make_pair(begin,end)) std::cout &lt;&lt; file.leaf() &lt;&lt; std::endl; } } </pre><p> The problem is that the function readdir_r_simulator() in boost/libs/filesystem/src/operations.cpp should return != 0 to signal error, but this line: </p> <pre class="wiki">{ return ::readdir_r( dirp, entry, result ); } </pre><p> returns 0 when readdir_r() returns NULL, which means an error. </p> <p> The attached patch should fix the problem. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/1578 Trac 1.4.3 raulh39@… Fri, 18 Jan 2008 20:39:04 GMT attachment set https://svn.boost.org/trac10/ticket/1578 https://svn.boost.org/trac10/ticket/1578 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">operations.cpp.patch</span> </li> </ul> <p> Patch for operations.cpp </p> Ticket Beman Dawes Sun, 20 Jan 2008 14:46:51 GMT status changed; milestone set https://svn.boost.org/trac10/ticket/1578#comment:1 https://svn.boost.org/trac10/ticket/1578#comment:1 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> <li><strong>milestone</strong> → <span class="trac-field-new">Boost 1.35.0</span> </li> </ul> <p> Sun supplies both POSIX and non-POSIX versions of readdir_r, according to <a class="ext-link" href="http://docs.sun.com/app/docs/doc/819-2243/readdir-3c?a=view"><span class="icon">​</span>http://docs.sun.com/app/docs/doc/819-2243/readdir-3c?a=view</a>. The compliant version is selected by defining _POSIX_PTHREAD_SEMANTICS. </p> <p> So it looks to me that the fix for ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/1578" title="#1578: Bugs: bug in readdir_r_simulator() in a multi-threaded environment (closed: worksforme)">#1578</a> (which is reporting the bug that results when the non-POSIX version is used) is to define _POSIX_PTHREAD_SEMANTICS at the beginning of boost-root/libs/filesystem/src/operations.cpp. This will cause the POSIX version to be used. </p> <p> I don't have access to a Sun system so can't test that. There is also a small chance that the same macro is used on some other platform in a conflicting way. </p> <p> I'd appreciate it if someone with access to a Sun system could test this (using the program given in the <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/1578" title="#1578: Bugs: bug in readdir_r_simulator() in a multi-threaded environment (closed: worksforme)">#1578</a>). If I don't hear anything in a day or so, I'll go ahead and make the change to the trunk. </p> <p> Thanks, </p> <p> --Beman </p> Ticket anonymous Mon, 21 Jan 2008 07:53:42 GMT <link>https://svn.boost.org/trac10/ticket/1578#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1578#comment:2</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/1578#comment:1" title="Comment 1">bemandawes</a>: </p> <blockquote class="citation"> <p> Sun supplies both POSIX and non-POSIX versions of readdir_r, according to <a class="ext-link" href="http://docs.sun.com/app/docs/doc/819-2243/readdir-3c?a=view"><span class="icon">​</span>http://docs.sun.com/app/docs/doc/819-2243/readdir-3c?a=view</a>. The compliant version is selected by defining _POSIX_PTHREAD_SEMANTICS. </p> </blockquote> <p> Yes, that's true. I didn't read all the man page. My fault. </p> <blockquote class="citation"> <p> So it looks to me that the fix for ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/1578" title="#1578: Bugs: bug in readdir_r_simulator() in a multi-threaded environment (closed: worksforme)">#1578</a> (which is reporting the bug that results when the non-POSIX version is used) is to define _POSIX_PTHREAD_SEMANTICS at the beginning of boost-root/libs/filesystem/src/operations.cpp. This will cause the POSIX version to be used. </p> </blockquote> <p> Yes, but _POSIX_PTHREAD_SEMANTICS is already defined at the beginning of operations.cpp... </p> <p> I have been investigating the problem. </p> <p> It happens that I am compiling in a 32 bits environment, and, because of that, the compiler defines _ILP32. But, at the beginning of operations.cpp you can find: </p> <pre class="wiki">#if !(defined(__HP_aCC) &amp;&amp; defined(_ILP32) &amp;&amp; \ !defined(_STATVFS_ACPP_PROBLEMS_FIXED)) # define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect, #endif </pre><p> As I don't define neither __HP_aCC nor _STATVFS_ACPP_PROBLEMS_FIXED, _FILE_OFFSET_BITS gets defined with a value of 64. But this is not correct, because if you do that, the posix version of readdir_r is not selected. </p> <p> (If you need an extract of dirent.h to verify this, I can send it to you, but it is 122 lines long so I prefer not to copy it here) </p> <p> So please, consider changing that lines to: </p> <pre class="wiki">#if !(defined(__HP_aCC) &amp;&amp; defined(_ILP32) &amp;&amp; \ !defined(_STATVFS_ACPP_PROBLEMS_FIXED)) &amp;&amp; \ !defined(__sun__) # define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect, #endif </pre><p> (and forget about the patch I submitted before) </p> <p> Thanks, Raúl. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Beman Dawes</dc:creator> <pubDate>Mon, 21 Jan 2008 14:09:02 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/1578#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1578#comment:3</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/1578#comment:2" title="Comment 2">anonymous</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/1578#comment:1" title="Comment 1">bemandawes</a>: </p> <blockquote class="citation"> <p> Sun supplies both POSIX and non-POSIX versions of readdir_r, according to <a class="ext-link" href="http://docs.sun.com/app/docs/doc/819-2243/readdir-3c?a=view"><span class="icon">​</span>http://docs.sun.com/app/docs/doc/819-2243/readdir-3c?a=view</a>. The compliant version is selected by defining _POSIX_PTHREAD_SEMANTICS. </p> </blockquote> <p> Yes, that's true. I didn't read all the man page. My fault. </p> <blockquote class="citation"> <p> So it looks to me that the fix for ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/1578" title="#1578: Bugs: bug in readdir_r_simulator() in a multi-threaded environment (closed: worksforme)">#1578</a> (which is reporting the bug that results when the non-POSIX version is used) is to define _POSIX_PTHREAD_SEMANTICS at the beginning of boost-root/libs/filesystem/src/operations.cpp. This will cause the POSIX version to be used. </p> </blockquote> <p> Yes, but _POSIX_PTHREAD_SEMANTICS is already defined at the beginning of operations.cpp... </p> </blockquote> <p> Duh... Sorry, I missed that. </p> <blockquote class="citation"> <p> I have been investigating the problem. </p> <p> It happens that I am compiling in a 32 bits environment, and, because of that, the compiler defines _ILP32. But, at the beginning of operations.cpp you can find: </p> <pre class="wiki">#if !(defined(__HP_aCC) &amp;&amp; defined(_ILP32) &amp;&amp; \ !defined(_STATVFS_ACPP_PROBLEMS_FIXED)) # define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect, #endif </pre><p> As I don't define neither __HP_aCC nor _STATVFS_ACPP_PROBLEMS_FIXED, _FILE_OFFSET_BITS gets defined with a value of 64. But this is not correct, because if you do that, the posix version of readdir_r is not selected. </p> <p> (If you need an extract of dirent.h to verify this, I can send it to you, but it is 122 lines long so I prefer not to copy it here) </p> <p> So please, consider changing that lines to: </p> <pre class="wiki">#if !(defined(__HP_aCC) &amp;&amp; defined(_ILP32) &amp;&amp; \ !defined(_STATVFS_ACPP_PROBLEMS_FIXED)) &amp;&amp; \ !defined(__sun__) # define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect, #endif </pre></blockquote> <p> But IIUC, that will disable large file support. See <a class="ext-link" href="http://docs.sun.com/app/docs/doc/816-5138/appendixa-tbl-10?a=view"><span class="icon">​</span>http://docs.sun.com/app/docs/doc/816-5138/appendixa-tbl-10?a=view</a> </p> <p> That document specifically lists _ILP32 and _FILE_OFFSET_BITS==64 as a valid combinations. I really would like to see the dirent.h header. I looked for it with Google, but couldn't find a copy. IANAL, but it seems to me that it would be fair use for me to look at a copy for debugging this problem. If you would like, I can ask someone at Sun to send me a copy. </p> <p> --Beman </p> </description> <category>Ticket</category> </item> <item> <dc:creator>raulh39</dc:creator> <pubDate>Thu, 14 Feb 2008 21:10:47 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/1578#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1578#comment:4</guid> <description> <p> Ok. I've been studying the problem, and I have come to the conclusion that it's a bug in Solaris. </p> <p> The function readdir_r (despite what is indicated here: <a class="ext-link" href="http://tinyurl.com/35aek7"><span class="icon">​</span>http://tinyurl.com/35aek7</a>) with </p> <blockquote> <p> int r = readdir_r(dirp,entry,result); </p> </blockquote> <p> returns r==-1, do NOT set *result to NULL, and leaves errno with its previous value when it reaches an end-of-directory. </p> <p> This way it "cheats" dir_itr_increment (lines 1269 and 1270 of operations.cpp in boost 1.34.1) to believe that an error has ocurred (because of the -1), but returns errno, whose value is 0, which means OK! </p> <p> So basic_directory_iterator&lt;Path&gt;::increment() understands (lines 940 to 944 of operations.hpp) that everything is OK, and because *result has not been set to NULL, m_imp-&gt;m_handle is not NULL, so (line 950) it is not understand as an end-of-directory. </p> <p> I have change readdir_r_simulator (lines 1247-1248) from this: </p> <pre class="wiki"> if ( ::sysconf( _SC_THREAD_SAFE_FUNCTIONS ) &gt;= 0 ) { return ::readdir_r( dirp, entry, result ); } </pre><p> to this: </p> <pre class="wiki"> if ( ::sysconf( _SC_THREAD_SAFE_FUNCTIONS ) &gt;= 0 ) { int r = ::readdir_r( dirp, entry, result ); #ifdef __sun__ if(r==-1 &amp;&amp; errno==0) { r=0; *result=0; } #endif return r; } </pre><p> and now it works as expected. </p> <p> Please consider whether this changes might be made in any branch of Boost. Thank you. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Beman Dawes</dc:creator> <pubDate>Wed, 25 Jun 2008 21:33:55 GMT</pubDate> <title>status changed https://svn.boost.org/trac10/ticket/1578#comment:5 https://svn.boost.org/trac10/ticket/1578#comment:5 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">new</span> </li> </ul> Ticket Beman Dawes Tue, 29 Jun 2010 11:42:51 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/1578#comment:6 https://svn.boost.org/trac10/ticket/1578#comment:6 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">worksforme</span> </li> </ul> <p> I've been testing on Open Solaris, and am not able to reproduce the reported results. </p> <p> Perhaps there was a bug in Solaris that has now been fixed. </p> <p> I'm closing this ticket, but will reopen if fresh information surfaces. Because I've now got Solaris running on my own machine (via <a class="missing wiki">VirtualBox</a>), I'd be able to respond much more quickly. </p> <p> Thanks, </p> <p> --Beman </p> Ticket