<div><div dir="auto">Errno is an easy example, but perhaps not the best specifically because the standard dictates its behavior.  But an implementation may have implicit assumptions as well.</div></div><div dir="auto"><br></div><div dir="auto">I guess let me make this concrete: can you propose a specific separation that you have in mind?</div><div dir="auto"><br></div><div dir="auto">Keep in mind that even if A doesn’t depend on B, that doesn’t mean that A and B can be separated.  You mentioned that open() and close() would obviously  have to be done at the same time, but it’s much worse than this: The *entire transitive closure* of open() and close() must be done at the same time, and my hypothesis is that this is going to a) be much larger than you expect, and b) be different with different underlying libc implementations.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">Then there are more immediate issues.  On Windows specifically, I’m not even sure it’s going to be physically possible to link in two copies of the CRT and have one forward to the other.  If it is possible, it’s very non obvious how to make it work and will likely require a ton of additional machinery.</div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jun 26, 2019 at 9:44 PM Siva Chandra <<a href="mailto:sivachandra@google.com">sivachandra@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> On 6/25/19 7:22 PM, Zachary Turner via llvm-dev wrote:<br>
> > I foresee problems with this on both Windows and non-Windows.  A<br>
> > typical libc implementation has a lot of internal state that is shared<br>
> > across API boundaries in a way that is considered an implementation<br>
> > detail.  So making assumptions about which state is shared and which<br>
> > isn't is going to be a problem.<br>
<br>
+1 for what Hal Finkel has said below about switching from redirectors<br>
to implementations: There will be certain groups of functions which<br>
will have to be switched all together. We will not be able to do it<br>
one function at a time for such groups.<br>
<br>
> > How do you guarantee that if you implement method A and forward method<br>
> > B, that B will behave the same as it would have if you had forwarded A<br>
> > also?  It might not even work at all.  Where can you safely draw this<br>
> > boundary?<br>
<br>
Are you talking about a scenario wherein implementation of B in the<br>
system libc calls its A? If yes, most libc implementations do a good<br>
job of using internal names in such scenarios. That is, B would call A<br>
with an internal name. This ensures that B from the system libc calls<br>
A also from the system libc and not the redirector/forwarder.<br>
<br>
> > Users can set errno for example, and in many cases they must set errno<br>
> > to 0 before invoking a call if they want to reliably detect an error.<br>
> > So let's say they set errno to 0, then call a method which our libc<br>
> > implementation decides to forward.  What do we do?  We could propagate<br>
> > errno on every single call, but my point is that there are going to be<br>
> > a ton of subtle issues that arise from this approach that are hard to<br>
> > foresee, precisely because the implementation details of a libc<br>
> > implementation are supposed to be just that - implementation details.<br>
<br>
Dealing with errno in particular is probably not as nasty as it seems.<br>
The standard allows errno to be a macro. Hence, for the transitory<br>
phase, implementations and redirectors in our libc can make use of the<br>
errno from the system libc. Something like this:<br>
<br>
$> cat llvm-errno.cpp<br>
#include <errno.h>  // This is the system-libc header file<br>
<br>
int *__llvm_errno() {<br>
  return &errno;<br>
}<br>
<br>
$> cat errno.h  # This is the llvm libc's errno.h<br>
int *__llvm_errno();<br>
<br>
#define errno (*__llvm_errno())<br>
<br>
On Tue, Jun 25, 2019 at 6:20 PM Finkel, Hal J. <<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>> wrote:<br>
> You certainly can't mix-and-match on a per-function level, in general. I<br>
> suspect that there are some subsystems that can be substituted. Using<br>
> open from one libc and close from another seems problematic. Using open<br>
> and close from one libc and qsort from another is probably fine. And, as<br>
> you point out, the library might need to be configurable to use an<br>
> externally-provided errno.<br>
</blockquote></div></div>