Re: StringNg review: MemBlob

2010-09-22 Thread Amos Jeffries

On 22/09/10 16:31, Alex Rousskov wrote:

On 09/20/2010 08:18 PM, Alex Rousskov wrote:

On 09/03/2010 09:21 AM, Kinkie wrote:


You'll find the branch at lp:~kinkie/squid/stringng

...

Comments for MemBlob.cci r9472:


Found one more:


* \note memcpy is used as the copying function. This is safe,
* because it is guarranteed by design that the copied-to
* memory area is only owned by the appended-to string,
* and thus doesn't overlap with the appended-from area
*/
void
MemBlob::append(const char *S, const MemBlob::size_type Ssize)
{
memcpy(mem+bufUsed,S,Ssize);
bufUsed+=Ssize;
++stats.append;
}


The \note is correct,


No. As you pointed out to me earlier with SBuf the S here may be the 
result of:

  a.clear(); a.append(a.mem, 1);

...



but we should not mention string in MemBlob.cci.
MemBlob does not (or should not) know what its users are. There may be a
better way to express the same thought. Consider:

\none memcpy() is safe because we copy to an unused area


*that* is better. There is still no guarantee it wont overflow on the 
destination. memcpy() makes no mention about when happens when one of 
the pointers is NULL, but experience shows a lot of segfaults.


memcpy() docs state always copies exactly num bytes and that the 
buffers should not overlap.


memmove() is the safe one which should be used if there is any doubt 
about overlapping memory. But even that can't validate against overflows.




The note belongs to the append() implementation, not its description.



Amos
--
Please be using
  Current Stable Squid 2.7.STABLE9 or 3.1.8
  Beta testers wanted for 3.2.0.2


Re: StringNg review: MemBlob

2010-09-22 Thread Kinkie
On Tue, Sep 21, 2010 at 4:18 AM, Alex Rousskov
rouss...@measurement-factory.com wrote:
 On 09/03/2010 09:21 AM, Kinkie wrote:

 You'll find the branch at lp:~kinkie/squid/stringng

 I decided to take a look at MemBlob because it is used by SBuf which was
 reviewed a few days ago. It would be nice to get a fixed SBuf committed, but
 that would require committing the classes it uses.

 Committing smaller self-contained parts may be an overall better strategy
 than trying to fix everything first and then do one huge commit.

 So here is a MemBlob review:

MemBlob and SBuf are meant to be used together. They split the burden
of managing memory correcly.

 Comments for src/MemBlob.h r9472:

 #include MemPool.h

Needed for MEMPROXY_CLASS etc

 Remove if not needed.

 #include RefCount.h

 /**
  * A container for various MemBlob class-wide statistics
  */
 class MemBlobStats {
     public:
     u_int64_t alloc; ///number of allocation operations

 Class allocations or buffer allocations?

Clarified. MemBlob allocations

     u_int64_t realloc; ///number of re-allocation operations

 .

     u_int64_t live; ///number of live references to bufs

 How can you know the number of references? Do you mean the number of MemBob
 instances in existence?

Number of MemBlob instances. Clarified.


     u_int64_t append; ///number of append operations (whtout grow)

 spelling
 Besides, MemBob does not grow!

Fixed

     u_int64_t allocatedBytes; ///the total size of the allocated storage

 Conflicts with the previous use of allocation. If that is not changed,
 use liveBytes here.

Done.

     /**
      * Dumps statistics to an ostream. Use an ostringstream to
      * capture them to a string
      */
     std::ostream dump(std::ostream os) const;

 Consider removing reference to ostringstream or moving it to some .dox file.
 It does not belong to interface documentation.

Fixed.

     MemBlobStats();
 };

 .

 /**
  * Low-level buffer. It's responsible for allocating and managing
  * the blocks of memory. It's refcounted, but it doesn't know
  * which SBufs hold references to it.
  */

 MemBlob does not manage blocks, it manages one block. It does not know many
 things (do not document what is not there).

Fixed


 Consider:
 /// A refcounted fixed-size buffer. Tracks the portion used by opaque
 content.

How about:
Refcounted memory buffer, content-agnostic. Meant to only be used by SBuf. ?


 class MemBlob: public RefCountable {
     public:
     typedef RefCountMemBlob Pointer;
     typedef unsigned int size_type;

 Would be nice to guarantee support for 5GB and larger blobs.

Do we need them now? It'll be trivial to extend when needed.

     char *mem;         /// The block of memory

 Missing  in Doxygen comments?

Yes. I wasn't aware of the construct.


 Consider: /// raw allocated memory

     size_type bufSize; /// Size of the allocated memory
     size_type bufUsed; /// How much of the memory is actually used

 Other Squid code is using capacity and size for this. Std::string also uses
 size() for user-facing buffer length. Please be consistent.

Changed, even though I find the name size confusing in this case.

 Remove the buf prefix until you have some other size and capacity members
 to distinction from. Besides, this is not a buf. This is a blob :-)

Yup. Relics... I've been working on this for more than two years now.

 I would not leave these data members public, but it is your call.

This class originally was private to SBuf. I've now clarified in the
class definition that it's not meant for general use; its only client
should be SBuf.

     _SQUID_INLINE_ void deleteSelf();

 I hope this can be removed. If not, it must be documented. The corresponding
 comments in .cci do not make sense to me and do not match RefCount.h in
 trunk, as far as I can tell.

http://old.squid-cache.org/Doc/Prog-Guide/prog-guide-24.html
http://markmail.org/message/kt7357pwttmzrey3

Maybe the documentaiton is outdated?

     MemBlob(const size_type size);

 Missing explicit. It is better to document whether it allocates anything.

Fixed.

     MemBlob(char * memBlock, const size_type memSize);

 Not sure why this is needed, but needs to be documented, especially with
 regard to memBlock ownership and destruction rules.

Documented.

 Please keep in mind that without a default constructor (and reserve()), it
 would be impossible to have containers of blobs.

Not needed. We want containers of SBufs, a MemBlob is more akin to a
smart struct.

     _SQUID_INLINE_ bool isAtEnd(const char *ptr) const;

 Missing documentation.
 Why is this needed? Some transitional call? If yes, document as such.

It is needed to know whether a the tail of a SBuf is at the tail of a
shared MemBlob. Such a SBuf can append without needing a cow, if
there's enough headroom in the MemBlob.

     _SQUID_INLINE_ size_type freeSpace() const;

 Missing documentation.

Renamed to getAvailableSpace. Documentation was in the .cci, moved it

 This reads like a command 

Re: StringNg review: MemBlob

2010-09-22 Thread Kinkie
On Wed, Sep 22, 2010 at 8:47 AM, Amos Jeffries squ...@treenet.co.nz wrote:
 On 22/09/10 16:31, Alex Rousskov wrote:

 On 09/20/2010 08:18 PM, Alex Rousskov wrote:

 On 09/03/2010 09:21 AM, Kinkie wrote:

 You'll find the branch at lp:~kinkie/squid/stringng

 ...

 Comments for MemBlob.cci r9472:

 Found one more:

 * \note memcpy is used as the copying function. This is safe,
 * because it is guarranteed by design that the copied-to
 * memory area is only owned by the appended-to string,
 * and thus doesn't overlap with the appended-from area
 */
 void
 MemBlob::append(const char *S, const MemBlob::size_type Ssize)
 {
 memcpy(mem+bufUsed,S,Ssize);
 bufUsed+=Ssize;
 ++stats.append;
 }

 The \note is correct,

 No. As you pointed out to me earlier with SBuf the S here may be the result
 of:
  a.clear(); a.append(a.mem, 1);

Using SBuf's raw memory access functions is dangerous, and this is
well documented.
It gives users rope, can't be blamed for how they use it..


 ...


 but we should not mention string in MemBlob.cci.
 MemBlob does not (or should not) know what its users are. There may be a
 better way to express the same thought. Consider:

 \none memcpy() is safe because we copy to an unused area

 *that* is better. There is still no guarantee it wont overflow on the
 destination. memcpy() makes no mention about when happens when one of the
 pointers is NULL, but experience shows a lot of segfaults.

Changed to reflect this.
MemBlob.mem can never be NULL; we could add a guard if the user passes
a NULL char*, and  treat it as a NOP.

 memcpy() docs state always copies exactly num bytes and that the buffers
 should not overlap.
 memmove() is the safe one which should be used if there is any doubt about
 overlapping memory. But even that can't validate against overflows.

Can change to memmove; is there a performance hit?


-- 
    /kinkie


Re: [PATCH] comm cleanup mk8 - src/comm only

2010-09-22 Thread Amos Jeffries

On 21/09/10 10:00, Alex Rousskov wrote:

On 09/19/2010 05:35 AM, Amos Jeffries wrote:

Round 2 of only src/comm/ changes.

I believe this accounts for all the bits requested to date. Including
adding Subscriptions for ConnAcceptor.


* The patch is missing the new Subscription class. Based on your subject
line, I am guessing you will post that separately.


* Comm::ConnOpener::start() should call connect() directly. Start() is
already async, there is no need to pay the async price again. Moreover,
by doing an async call, you are more likely to encounter timeouts even
before we call connect() because the clock starts ticking before the
call is fired.


Done.



* Comm::ConnOpener::timeout() should call connect() directly. Timeout()
is already async, there is no need to pay the async price again.



Done.


* I do not like how Comm::ConnOpener::connect() calls itself. I assume
you did not invent this, but the code will fail to produce the
intended(?) delay if there are no other async calls already scheduled,
which is something the class does not really control. Recall that async
calls are AsyncCallQueue::fire()d until there are none left...

At the very least, please add a comment explaining why we use such a
hack instead of either using an explicit loop or waiting a little bit
via eventAdd.



I think you asked me to remove eventAdd a while back before this was a 
Job. Reverted to the old .05 sec delay.




* calls_.connect_ should not be reused in Comm::ConnOpener::connect()
because AsyncCall objects may not support being fired twice -- they may
have state. The connect_ object is not needed at all if you address the
above comments. If you do not, set it to NULL at the start of
Comm::ConnOpener::connect() and recreate when needed.


Oops. sorry. Foxed.




* I may be wrong, but the interesting Is opened conn fully open?
comment below may reveal a couple of bugs:


+ // recover what we can from the job
+ if (conn_ != NULL  conn_-isOpen()) {
+ // it never reached fully open, so abort the FD
+ conn_-close();
+ ...


Clearly, conn_ is open inside that if-statement (there is no such thing
as half-open conn, I hope; we have enough headaches from half-closed


sorry, no such luck. see COMM_INPROGRESS.
As I understand it:
 For the period between comm_connect_addr() returning and a signal 
being received (via the write handler being called) that write access is 
possible the FD is in fact half-open.
 The kernel seems to have allocated a FD and returned (non-blocking) 
but still be awaiting the network SYN-ACK.


The headaches here are small since only the opening sequence job and the 
fd_table is involved. We just have to cleanup the conn_-fd before 
passing control of conn_ back out to any other part of Squid.



ones!). There is nothing wrong with the connection. Instead, it is the
ConnOpener job itself that got into a half-finished state here, most


Yes. Nothing wrong, but we can't use the FD the system gave us already.


likely due to an exception after the connection got opened and before it
was sent to the caller. To clean up, two separate actions are needed:

a) Close the opened connection. The beginning of your if-statement will
do the job, but do not call doneConnecting(). Here is a polished version:

if (conn_ != NULL  conn_-isOpen()) {
Must(callback_ != NULL); // or there should be no conn_
// we never sent this open connection to the caller, so close
conn_-close();
fd_table[conn_-fd].flags.open = 0;
conn_ = NULL;
}

b) Notify the caller we are dying:

if (callback_ != NULL) {
// do not let the caller wait forever
doneConnecting(COMM_ERR_CONNECT, 0);
}

I am not sure about the order. The above order means caller can handle
and should get nil params.conn. You can remove conn_ = NULL if
caller should get a non-nil but closed params.conn, but there will
still be two if-statements.


Good idea. Above order is correct. params.conn may contain the attempted 
local/remote IP combos for use by the callers recovery. !COMM_OK status 
guarantees that the FD is not safely usable.


I also see that I missed clearing the write handler before fully closing 
conn_. do the timeout and closing handlers need to be explicitly 
removed? or are they happy with the cancels?




* Consider moving case COMM_OK code, including lookupLocalAddress() to
something like Connection::opened(). The code seems to be manipulating
conn_ without access to Comm::ConnOpener data except perhaps host_. I
could have missed some other dependencies, of course, but it feels like
a Connection business to set things up after the connection has been
established. The ConnOpener job is done at that stage.


Done.




* Can we leave resetting fd_table[conn_-fd].flags.open to comm_close(),
which will be called from via conn_-close()? It feels wrong to force it
to zero way before the connection is actually closed but I understand
that you may be fighting some hidden dependencies.


We can. It was me being paranoid rather than known problems.

Considering 

Re: StringNg review: MemBlob

2010-09-22 Thread Amos Jeffries

On 22/09/10 21:30, Kinkie wrote:

On Tue, Sep 21, 2010 at 4:18 AM, Alex Rousskov
rouss...@measurement-factory.com  wrote:

On 09/03/2010 09:21 AM, Kinkie wrote:


You'll find the branch at lp:~kinkie/squid/stringng


I decided to take a look at MemBlob because it is used by SBuf which was
reviewed a few days ago. It would be nice to get a fixed SBuf committed, but
that would require committing the classes it uses.

Committing smaller self-contained parts may be an overall better strategy
than trying to fix everything first and then do one huge commit.

So here is a MemBlob review:



snip

Remove the buf prefix until you have some other size and capacity members
to distinction from. Besides, this is not a buf. This is a blob :-)


Yup. Relics... I've been working on this for more than two years now.


I would not leave these data members public, but it is your call.


This class originally was private to SBuf. I've now clarified in the
class definition that it's not meant for general use; its only client
should be SBuf.


If still relevant that would be reason for protected: and friend 
declarations in the class definition instead of public:.





 _SQUID_INLINE_ void deleteSelf();


I hope this can be removed. If not, it must be documented. The corresponding
comments in .cci do not make sense to me and do not match RefCount.h in
trunk, as far as I can tell.


http://old.squid-cache.org/Doc/Prog-Guide/prog-guide-24.html
http://markmail.org/message/kt7357pwttmzrey3

Maybe the documentaiton is outdated?



Seems to be. The RefCountable classes no longer have deleteSelf.



 _SQUID_INLINE_ bool isAtEnd(const char *ptr) const;


Missing documentation.
Why is this needed? Some transitional call? If yes, document as such.


It is needed to know whether a the tail of a SBuf is at the tail of a
shared MemBlob. Such a SBuf can append without needing a cow, if
there's enough headroom in the MemBlob.


So, a char* way of saying:

 if (SBuf::off_+Sbuf::len_ == MemBlob::size 
 SBuf::off_+Sbuf::len_  MemBlob::capacity) {
 ...

with canAppend being a duplicate as above but = MemBlob::capacity+N

or rather isAtEnd being a case of canAppend(0)



This reads like a command to free some space.
Consider: spaceSize()
spaceSize() would be more consistent with other Squid code as well.



 _SQUID_INLINE_ bool canGrow(const size_type howmuch) const;


Missing documentation.
Usually unsafe and wastefull. See similar comments for SBuf.


It'd be unsafe in a concurrent (multithreaded) environment; how would
it be unsafe in a single-threaded env?



Squid won't be single-threaded for much longer. At least on the 
timescale for string-level changes.




 _SQUID_INLINE_ bool canAppend(char const * bufEnd, const size_type
howmuch) const;


Missing documentation.
Especially since it is not clear why canAppend() needs a pointer.
Looking at the .cci implementation, I question why would the caller
keep the bufEnd pointer if MemBlob manages it already? I do not think this
call or duplicated bufEnd pointer is needed.


if many SBufs reference the same MemBlob, an append operation to one
of them does not need a cow if the appended-to SBuf is at the tail of
the MemBlob and there is enough free space at the end of the MemBlob
to hold the data being appended.
This canAppend call checks exactly that. the SBuf knows its own tail,
while the MemBlob knows the tail of the used portion of itself.



see isAtEnd() comment above.


/**
  * constructor, creates an empty MemBlob of size= requested
  * \param size the minimum size to be guarranteed from the MemBlob
  */
MemBlob::MemBlob(const MemBlob::size_type size)
{
 debugs(MEMBLOB_DEBUGSECTION,9,HERE  size=  size);
 memAlloc(size);
}


I would recommend initializing mem and sizes to NULL/0s explicitly in all
the constructors.  It does not cost much and may save a few hours of
debugging if things go wrong.


Isn't setting them in memAlloc enough? Besides the actual size may be
different (or would you mean to set them twice?)


In the constructor init list.

You can then enforce the MUST and ONLY requirements with 
assert(mem==NULL) etc at the start of memAlloc.



Amos
--
Please be using
  Current Stable Squid 2.7.STABLE9 or 3.1.8
  Beta testers wanted for 3.2.0.2


Re: StringNg review: MemBlob

2010-09-22 Thread Alex Rousskov

On 09/22/2010 03:30 AM, Kinkie wrote:

On Tue, Sep 21, 2010 at 4:18 AM, Alex Rousskov wrote:

On 09/03/2010 09:21 AM, Kinkie wrote:


You'll find the branch at lp:~kinkie/squid/stringng




/**
  * Low-level buffer. It's responsible for allocating and managing
  * the blocks of memory. It's refcounted, but it doesn't know
  * which SBufs hold references to it.
  */



Consider:
/// A refcounted fixed-size buffer. Tracks the portion used by opaque
content.


How about:
Refcounted memory buffer, content-agnostic. Meant to only be used by SBuf. ?


Fixed-size is an key property unless you think it may change soon.
Content-agnostic is fine, I guess.

As for meant to only be used by Foo, I am still against such 
restrictions on use in general and in this context in particular. We 
have discussed this before. Use-cases may determine the initial design 
sketch and optimizations, but the final APIs should be usable in any 
context that needs them rather than restricted to one specific user. 
MemBlob is no exception IMO.




class MemBlob: public RefCountable {
 public:
 typedef RefCountMemBlob  Pointer;
 typedef unsigned int size_type;


Would be nice to guarantee support for 5GB and larger blobs.


Do we need them now? It'll be trivial to extend when needed.


I may need them soon. Based on past experience, I am not convinced that 
replacing 'int' with some other type will be trivial.




I would not leave these data members public, but it is your call.


This class originally was private to SBuf. I've now clarified in the
class definition that it's not meant for general use; its only client
should be SBuf.


Which is a wrong restriction made worse by wrongly guessed implications. 
As SBuf review shows, we are already paying the price for the lack of 
proper boundaries between the two classes. It makes some areas of the 
SBuf code confusing at best.




 _SQUID_INLINE_ void deleteSelf();


I hope this can be removed. If not, it must be documented. The corresponding
comments in .cci do not make sense to me and do not match RefCount.h in
trunk, as far as I can tell.


http://old.squid-cache.org/Doc/Prog-Guide/prog-guide-24.html
http://markmail.org/message/kt7357pwttmzrey3

Maybe the documentaiton is outdated?


That old documentation is wrong. Use the source code. Remove deleteSelf().



 _SQUID_INLINE_ size_type freeSpace() const;


Missing documentation.


Renamed to getAvailableSpace. Documentation was in the .cci, moved it


Wrong name. The method does not give the caller the available space, 
only its size. Here are some combinations that work better:


   size(), spaceSize(), capacity()
   contentSize(), spaceSize(), capacity()
   usedSize() and availableSize(), capacity()




MemBlobStats MemBlob::stats;


If some static code wants to allocate MemBlob, will its stats not get
counted, depending on static initialization order?


Yes. I don't think that's much of an issue;


It becomes an issue when we get bug reports about negative or too-big 
counters. Or when somebody adds an assert() that the counter is correct. 
Both have happened before.



 stats are mostly meant to

help us diagnose the effectiveness of the solution, and in fact I
wouldn't be against #ifdef-ing them out in production code.


Sure, nobody cares about effectiveness of the code in production as long 
as it was effective in the lab :-).




/**
  * constructor, creates an empty MemBlob of size= requested
  * \param size the minimum size to be guarranteed from the MemBlob
  */
MemBlob::MemBlob(const MemBlob::size_type size)
{
 debugs(MEMBLOB_DEBUGSECTION,9,HERE  size=  size);
 memAlloc(size);
}


I would recommend initializing mem and sizes to NULL/0s explicitly in all
the constructors.  It does not cost much and may save a few hours of
debugging if things go wrong.


Isn't setting them in memAlloc enough? Besides the actual size may be
different (or would you mean to set them twice?)


Initialize them to NULLs and 0s before calling memAlloc. Such 
initializations cost little and avoid having an object with 
uninitialized members.



Thank you,

Alex.


Re: [PATCH] comm cleanup mk8 - src/comm only

2010-09-22 Thread Alex Rousskov

On 09/22/2010 08:28 AM, Amos Jeffries wrote:

On 21/09/10 10:00, Alex Rousskov wrote:

On 09/19/2010 05:35 AM, Amos Jeffries wrote:



* I do not like how Comm::ConnOpener::connect() calls itself. I assume
you did not invent this, but the code will fail to produce the
intended(?) delay if there are no other async calls already scheduled,
which is something the class does not really control. Recall that async
calls are AsyncCallQueue::fire()d until there are none left...

At the very least, please add a comment explaining why we use such a
hack instead of either using an explicit loop or waiting a little bit
via eventAdd.



I think you asked me to remove eventAdd a while back before this was a
Job. Reverted to the old .05 sec delay.


I could have made the wrong call, you could have interpreted my comment 
incorrectly, or both. If you want to review what happened, please find 
and repost that conversation.




* I may be wrong, but the interesting Is opened conn fully open?
comment below may reveal a couple of bugs:


+ // recover what we can from the job
+ if (conn_ != NULL  conn_-isOpen()) {
+ // it never reached fully open, so abort the FD
+ conn_-close();
+ ...


Clearly, conn_ is open inside that if-statement (there is no such thing
as half-open conn, I hope; we have enough headaches from half-closed


sorry, no such luck. see COMM_INPROGRESS.


I see. Fortunately, my swanSong() fix still applied.


I also see that I missed clearing the write handler before fully closing
conn_. do the timeout and closing handlers need to be explicitly
removed? or are they happy with the cancels?


AFAIK, comm_close() will remove those handlers automagically because it 
will call them with COMM_ERR_CLOSING. However, our code needs to make 
sure that it can handle such callbacks until swanSong() is called.




Considering no other jobs etc have anything validly pending on this
brand new FD should I be calling fd_close(conn_-fd) here instead of
conn_-close()?


In general, if you used comm_open, use comm_close.

If comm_close works, let's use it, avoiding low-level calls we should 
not even have access to. Comm itself may have something pending on that 
new FD...




* Can you explain how syncWithComm() side effects hit
theCallSub-callback()? Is not theCallSub-callback() itself constant
and its result is stored in a local variable? I do not understand how
syncWithComm() can affect theCallSub itself. Thank you.



Possibly obsolete now.

Dialer copy-constructors was initially created using getDialer() which
call syncWithComm() which in CommIoCb child class updates this-* state.
Fallout of that is that:
the CommIoCb constructor cant take a const parameter,
the parent class cant provide a const overload constructor,
the other children cant either,
callback() using copy-constructor cant be const.

I *think* the copy constructors are okay using raw dialer pointers now.
Which means everything down the chain can be const.



I cannot comment on that without seeing the new call-copying code.




* cbdataReferenceDone() already sets its parameter to NULL. No need to
do that twice:

+ /* clear any previous ptr */
+ if (_peer) {
+ cbdataReferenceDone(_peer);
+ _peer = NULL;
+ }




Great.
At this random point we are not sure its valid. For now I've make the
if() use the fixed getPeer().


That would leak _peer if it became invalid (unless you call 
cbdataReferenceDone(_peer) in getPeer() now, which would be technically 
correct and efficient but weird).



Would it be correct to use
cbdataReferenceValidDone(NULL, _peer) unconditionally here with no
callback? instead of separate validate and done?


You do not care about _peer validity or value because you are not 
dereferencing that pointer. Just do:


cbdataReferenceDone(_peer);

No ifs, no setting to NULL, no getPeer().



* Consider s/_peer/peer_/ in Connection for consistency with most other
code.


The struct peer_ global symbol clashes and gcc complains about missing
; or = after variable struct.
I don't plan on fighting that one just yet. Will mark it to be done though.


Agreed. The struct should be renamed (to Peer?), but that is not your 
problem. You can use just peer for the member name, I guess.




* s/unused//g. C++ does not require naming unused parameters.


Done. And converted the two places (commSetSelect and eventAdd wrappers)
to use JobCallback with NullaryMemFunT dialers on connect().


Not sure what you mean. Will become clear when the code is posted, I guess.


Cheers,

Alex.


Re: StringNg review: MemBlob

2010-09-22 Thread Alex Rousskov

On 09/22/2010 12:47 AM, Amos Jeffries wrote:

On 22/09/10 16:31, Alex Rousskov wrote:

On 09/20/2010 08:18 PM, Alex Rousskov wrote:

On 09/03/2010 09:21 AM, Kinkie wrote:


You'll find the branch at lp:~kinkie/squid/stringng

...

Comments for MemBlob.cci r9472:


Found one more:


* \note memcpy is used as the copying function. This is safe,
* because it is guarranteed by design that the copied-to
* memory area is only owned by the appended-to string,
* and thus doesn't overlap with the appended-from area
*/
void
MemBlob::append(const char *S, const MemBlob::size_type Ssize)
{
memcpy(mem+bufUsed,S,Ssize);
bufUsed+=Ssize;
++stats.append;
}


The \note is correct,


No. As you pointed out to me earlier with SBuf the S here may be the
result of:
a.clear(); a.append(a.mem, 1);


The situation here is different, I believe, but I do not understand your 
example. What is a? MemBlob does not have clear(). SBuf does not have 
mem...


If s* are SBufs and you meant

  s1.clear(); s1.append(s1.buf(), s1.size())

then it is fine because s1.size() will be zero.

If you meant

  s1.clear(); s1.append(s2.buf(), s2.size())

then it is fine because s1.append will COW if s1 and s2 share MemBlob 
and s2.size() is positive.


If you mean

 blob.clear; blob.append(blob.mem, blob.size())

then it is fine because blob.size() will be zero.




...



but we should not mention string in MemBlob.cci.
MemBlob does not (or should not) know what its users are. There may be a
better way to express the same thought. Consider:

\none memcpy() is safe because we copy to an unused area


*that* is better. There is still no guarantee it wont overflow on the
destination. memcpy() makes no mention about when happens when one of
the pointers is NULL, but experience shows a lot of segfaults.


The MemBlob append() code should not call memcpy() with a NULL 
destination pointer, of course, but that is not related to the \note. My 
understanding is that blob.mem is never NULL.


The MemBlob append() code must check for overflows. If I did not comment 
on that before, please consider this a please fix comment.


Kinkie, while you are at it, please also avoid calling memcpy/move() 
when size-to-append is zero, just in case.




memcpy() docs state always copies exactly num bytes and that the
buffers should not overlap.

memmove() is the safe one which should be used if there is any doubt
about overlapping memory. But even that can't validate against overflows.


Per \note, I think we are fine with memcpy() here but counter-examples 
are more than welcome. I assume memcpy() is significantly faster in some 
environments we care about.


On the other hand, if memmove() implementations we care about always 
quickly check for overlaps and actually call memcpy() when possible, 
then we should just use memmove()!


Thank you,

Alex.


Re: StringNg review: MemBlob

2010-09-22 Thread Alex Rousskov

On 09/22/2010 03:44 AM, Kinkie wrote:

On Wed, Sep 22, 2010 at 8:47 AM, Amos Jeffriessqu...@treenet.co.nz  wrote:

On 22/09/10 16:31, Alex Rousskov wrote:


On 09/20/2010 08:18 PM, Alex Rousskov wrote:


On 09/03/2010 09:21 AM, Kinkie wrote:


You'll find the branch at lp:~kinkie/squid/stringng


...


Comments for MemBlob.cci r9472:


Found one more:


* \note memcpy is used as the copying function. This is safe,
* because it is guarranteed by design that the copied-to
* memory area is only owned by the appended-to string,
* and thus doesn't overlap with the appended-from area
*/
void
MemBlob::append(const char *S, const MemBlob::size_type Ssize)
{
memcpy(mem+bufUsed,S,Ssize);
bufUsed+=Ssize;
++stats.append;
}


The \note is correct,


No. As you pointed out to me earlier with SBuf the S here may be the result
of:
  a.clear(); a.append(a.mem, 1);


Using SBuf's raw memory access functions is dangerous, and this is
well documented.
It gives users rope, can't be blamed for how they use it..


This has little to do with raw memory access, actually.

If a is SBuf and a.mem is a.buf(), then

 a.clear(); a.append(a.buf(), 1);

is wrong not because some areas overlap (they actually do not, see my 
earlier response) but because a.size() is less than 1 after a.clear() 
and so the caller should not be using 1 as the size-to-append 
parameter. In other words, there is a bug, but the bug is not in the 
append(), but in the caller code.


I just realized that SBuf uses length() instead of standard size(). I 
hope you got the idea though. :-(


Alex.


Does no-store in request imply no-cache?

2010-09-22 Thread Alex Rousskov

Hello,

One interpretation of RFC 2616 allows the proxy to serve hits when 
the request contains Cache-Control: no-store. Do you think such an 
interpretation is valid?


  no-store
  The purpose of the no-store directive is to prevent the
  inadvertent release or retention of sensitive information (for
  example, on backup tapes). The no-store directive applies to the
  entire message, and MAY be sent either in a response or in a
  request. If sent in a request, a cache MUST NOT store any part of
  either this request or any response to it.

Thank you,

Alex.


Re: Does no-store in request imply no-cache?

2010-09-22 Thread Kinkie
On Wed, Sep 22, 2010 at 8:27 PM, Alex Rousskov
rouss...@measurement-factory.com wrote:
 Hello,

    One interpretation of RFC 2616 allows the proxy to serve hits when the
 request contains Cache-Control: no-store. Do you think such an
 interpretation is valid?

  no-store
      The purpose of the no-store directive is to prevent the
      inadvertent release or retention of sensitive information (for
      example, on backup tapes). The no-store directive applies to the
      entire message, and MAY be sent either in a response or in a
      request. If sent in a request, a cache MUST NOT store any part of
      either this request or any response to it.

Hi,
No; IMVHO it means that it can be stored in RAM, but not swapped out
to a cache_dir.
no-store = no-cache is a conservative (but valid) approximation.


-- 
    /kinkie


Re: Does no-store in request imply no-cache?

2010-09-22 Thread Alex Rousskov

On 09/22/2010 02:46 PM, Kinkie wrote:

On Wed, Sep 22, 2010 at 8:27 PM, Alex Rousskov
rouss...@measurement-factory.com  wrote:

Hello,

One interpretation of RFC 2616 allows the proxy to serve hits when the
request contains Cache-Control: no-store. Do you think such an
interpretation is valid?

  no-store
  The purpose of the no-store directive is to prevent the
  inadvertent release or retention of sensitive information (for
  example, on backup tapes). The no-store directive applies to the
  entire message, and MAY be sent either in a response or in a
  request. If sent in a request, a cache MUST NOT store any part of
  either this request or any response to it.


Hi,
No; IMVHO it means that it can be stored in RAM, but not swapped out
to a cache_dir.


Looks like my question was not clear. Let me try to rephrase:

Assume Squid received a regular request and cached (does not matter 
where) the corresponding response. That request and that response had no 
Cache-Control headers. Everything is fine and ordinary. Now comes a 
second request for that cached object. The request has a Cache-Control: 
no-store header. Can Squid satisfy that no-store request from the cache?


Thank you,

Alex.


Re: Does no-store in request imply no-cache?

2010-09-22 Thread Mark Nottingham
Strictly, as a request directive it means you can't store the response to this 
request -- it says nothing about whether or not you can satisfy the request 
from a cache.

However, I imagine most people would interpret it as implying no-cache; 
you're still conformant if you do.

See also:
  http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-11#section-3.2.1


On 23/09/2010, at 4:27 AM, Alex Rousskov wrote:

 Hello,
 
 One interpretation of RFC 2616 allows the proxy to serve hits when 
 the request contains Cache-Control: no-store. Do you think such an 
 interpretation is valid?
 
   no-store
   The purpose of the no-store directive is to prevent the
   inadvertent release or retention of sensitive information (for
   example, on backup tapes). The no-store directive applies to the
   entire message, and MAY be sent either in a response or in a
   request. If sent in a request, a cache MUST NOT store any part of
   either this request or any response to it.
 
 Thank you,
 
 Alex.

--
Mark Nottingham   m...@yahoo-inc.com




Re: Does no-store in request imply no-cache?

2010-09-22 Thread Alex Rousskov

On 09/22/2010 05:05 PM, Mark Nottingham wrote:


Strictly, as a request directive it means you can't store the
response to this request -- it says nothing about whether or not you
can satisfy the request from a cache.


Hi Mark,

Let's assume the above is correct and Squid satisfied the no-store 
request from the cache. Should Squid purge the cached response afterwards?


If Squid does not purge, the next regular request will get the same 
cached response as the no-store request got, kind of violating the MUST 
NOT store any response to it no-store requirement.


If Squid purges, it is kind of silly because earlier requests could have 
gotten the same sensitive information before the no-store request came 
and declared the already cached information sensitive.


Thank you,

Alex.



See also:
   http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-11#section-3.2.1


On 23/09/2010, at 4:27 AM, Alex Rousskov wrote:


Hello,

 One interpretation of RFC 2616 allows the proxy to serve hits when
the request contains Cache-Control: no-store. Do you think such an
interpretation is valid?

   no-store
   The purpose of the no-store directive is to prevent the
   inadvertent release or retention of sensitive information (for
   example, on backup tapes). The no-store directive applies to the
   entire message, and MAY be sent either in a response or in a
   request. If sent in a request, a cache MUST NOT store any part of
   either this request or any response to it.

Thank you,

Alex.


--
Mark Nottingham   m...@yahoo-inc.com





Re: Does no-store in request imply no-cache?

2010-09-22 Thread Mark Nottingham

On 23/09/2010, at 9:47 AM, Alex Rousskov wrote:
 
 Hi Mark,
 
 Let's assume the above is correct and Squid satisfied the no-store 
 request from the cache. Should Squid purge the cached response afterwards?
 
 If Squid does not purge, the next regular request will get the same 
 cached response as the no-store request got, kind of violating the MUST NOT 
 store any response to it no-store requirement.

Sort of, but not really. I agree this could be worded better; we'll work on it.

 If Squid purges, it is kind of silly because earlier requests could have 
 gotten the same sensitive information before the no-store request came and 
 declared the already cached information sensitive.

Agreed. 

This has been discussed in the WG before (can't remember the ref); basically, 
it boiled down to each request being independent; you don't want requests 
affecting other ones (beyond anything, it's a security issue if you allow 
clients to purge your cache indescriminantly). 

--
Mark Nottingham   m...@yahoo-inc.com




Re: Does no-store in request imply no-cache?

2010-09-22 Thread Amos Jeffries
On Wed, 22 Sep 2010 17:47:57 -0600, Alex Rousskov
rouss...@measurement-factory.com wrote:
 On 09/22/2010 05:05 PM, Mark Nottingham wrote:
 
 Strictly, as a request directive it means you can't store the
 response to this request -- it says nothing about whether or not you
 can satisfy the request from a cache.
 
 Hi Mark,
 
  Let's assume the above is correct and Squid satisfied the no-store 
 request from the cache. Should Squid purge the cached response
afterwards?
 
 If Squid does not purge, the next regular request will get the same 
 cached response as the no-store request got, kind of violating the MUST

 NOT store any response to it no-store requirement.
 
 If Squid purges, it is kind of silly because earlier requests could have

 gotten the same sensitive information before the no-store request came

 and declared the already cached information sensitive.
 
 Thank you,
 
 Alex.

I take it as meaning only that any new copy received must not be saved or
used to update/replace existing copies.

Assuming no-cache is updating the existing copy (removal).

client A, B, C in sequence with B using no-store fetch the same thing.
 client C would be getting same response as client A, no problem.
 client B could have used no-cache+no-store if it wanted new content not
shared with C.

Amos

 See also:
   
http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-11#section-3.2.1


 On 23/09/2010, at 4:27 AM, Alex Rousskov wrote:

 Hello,

  One interpretation of RFC 2616 allows the proxy to serve hits
when
 the request contains Cache-Control: no-store. Do you think such an
 interpretation is valid?

no-store
The purpose of the no-store directive is to prevent the
inadvertent release or retention of sensitive information (for
example, on backup tapes). The no-store directive applies to
the
entire message, and MAY be sent either in a response or in a
request. If sent in a request, a cache MUST NOT store any part
of
either this request or any response to it.

 Thank you,

 Alex.

 --
 Mark Nottingham   m...@yahoo-inc.com



Build failed in Hudson: 3.HEAD-i386-OpenBSD #580

2010-09-22 Thread noc
See http://build.squid-cache.org/job/3.HEAD-i386-OpenBSD/580/changes

Changes:

[Amos Jeffries squ...@treenet.co.nz] Author: Various Translators
Translations Update auto-save

[Alex Rousskov rouss...@measurement-factory.com] HTTP Compliance: Make date 
parser stricter to better handle malformed Expires.

Check that there is no zone or zone is GMT in parse_date_elements().
Make sure there is no junk at the end of date in parse_date().

This will affect Date, IMS, and other date-carrying header fields recognized
by Squid but should not cause any messages to be rejected. Squid would just
ignore the malformed headers as if they are not there.

Co-Advisor test case:
test_case/rfc2616/invalidExpiresMakesStale-rfc1123x

[Alex Rousskov rouss...@measurement-factory.com] HTTP Compliance: do not 
remove ETag header from partial responses

RFC 2616 section 10.2.7 says that partial responses MUST include ETag
header if it would have been sent in a 200 response to the same request.

Co-Advisor test cases:
test_case/rfc2616/scHdrs-206-include-explicit-withVary-noIfs
test_case/rfc2616/scHdrs-206-include-explicit-woutVary-noIfs
test_case/rfc2616/scHdrs-206-include-other-If-Range-strong

[Automatic source maintenance squid...@squid-cache.org] SourceFormat 
Enforcement

--
[...truncated 3098 lines...]
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: strcat() is almost always misused, please use strlcat()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: sprintf() is often misused, please use snprintf()
Making all in POP3
sed -e 's,[...@]perl[@],/usr/bin/perl,g' 
../../../../helpers/basic_auth/POP3/basic_pop3_auth.pl.in basic_pop3_auth || 
(/bin/rm -f -f basic_pop3_auth ; exit 1)
Making all in RADIUS
if ccache g++ -DHAVE_CONFIG_H  -I../../../.. -I../../../../include 
-I../../../../src  -I../../../include -I/usr/local/include
-I../../../../helpers/basic_auth/RADIUS-Wall -Wpointer-arith 
-Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT -g -O2 -MT 
basic_radius_auth.o -MD -MP -MF .deps/basic_radius_auth.Tpo -c -o 
basic_radius_auth.o ../../../../helpers/basic_auth/RADIUS/basic_radius_auth.cc; 
 then mv -f .deps/basic_radius_auth.Tpo .deps/basic_radius_auth.Po; else rm 
-f .deps/basic_radius_auth.Tpo; exit 1; fi
if ccache g++ -DHAVE_CONFIG_H  -I../../../.. -I../../../../include 
-I../../../../src  -I../../../include -I/usr/local/include
-I../../../../helpers/basic_auth/RADIUS-Wall -Wpointer-arith 
-Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT -g -O2 -MT radius-util.o 
-MD -MP -MF .deps/radius-util.Tpo -c -o radius-util.o 
../../../../helpers/basic_auth/RADIUS/radius-util.cc;  then mv -f 
.deps/radius-util.Tpo .deps/radius-util.Po; else rm -f 
.deps/radius-util.Tpo; exit 1; fi
/bin/sh ../../../libtool --tag=CXX --mode=link ccache g++ -Wall -Wpointer-arith 
-Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT  -g -O2  -g -o 
basic_radius_auth  basic_radius_auth.o  radius-util.o -L../../../lib -lmiscutil 
 ../../../compat/libcompat.la-lm 
libtool: link: ccache g++ -Wall -Wpointer-arith -Wwrite-strings -Wcomments 
-Werror -pipe -D_REENTRANT -g -O2 -g -o basic_radius_auth basic_radius_auth.o 
radius-util.o  
-Lhttp://build.squid-cache.org/job/3.HEAD-i386-OpenBSD/ws/btlayer-00-default/squid-3.HEAD-BZR/_build/lib
 -lmiscutil ../../../compat/.libs/libcompat.a -lm
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: vsprintf() is often misused, please use vsnprintf()
basic_radius_auth.o(.text+0x128): In function `main':
../../../../helpers/basic_auth/RADIUS/basic_radius_auth.cc:471: warning: 
strcpy() is almost always misused, please use strlcpy()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: strcat() is almost always misused, please use strlcat()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: sprintf() is often misused, please use snprintf()
Making all in fake
if ccache g++ -DHAVE_CONFIG_H  -I../../../.. -I../../../../include 
-I../../../../src  -I../../../include -I/usr/local/include   -Wall 
-Wpointer-arith -Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT -g -O2 
-MT fake.o -MD -MP -MF .deps/fake.Tpo -c -o fake.o 
../../../../helpers/basic_auth/fake/fake.cc;  then mv -f .deps/fake.Tpo 
.deps/fake.Po; else rm -f .deps/fake.Tpo; exit 1; fi
/bin/sh ../../../libtool --tag=CXX --mode=link ccache g++ -Wall -Wpointer-arith 
-Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT  -g -O2  -g -o 
basic_fake_auth  fake.o -L../../../lib -lmiscutil  ../../../compat/libcompat.la 
libtool: link: ccache g++ -Wall -Wpointer-arith -Wwrite-strings -Wcomments 
-Werror -pipe -D_REENTRANT -g -O2 -g -o basic_fake_auth fake.o  
-Lhttp://build.squid-cache.org/job/3.HEAD-i386-OpenBSD/ws/btlayer-00-default/squid-3.HEAD-BZR/_build/lib
 -lmiscutil ../../../compat/.libs/libcompat.a

Build failed in Hudson: 3.HEAD-i386-OpenBSD #581

2010-09-22 Thread noc
See http://build.squid-cache.org/job/3.HEAD-i386-OpenBSD/581/changes

Changes:

[Amos Jeffries squ...@treenet.co.nz] Author: Various Translators
Translations Update auto-save

--
[...truncated 3094 lines...]
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: strcat() is almost always misused, please use strlcat()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: sprintf() is often misused, please use snprintf()
Making all in POP3
sed -e 's,[...@]perl[@],/usr/bin/perl,g' 
../../../../helpers/basic_auth/POP3/basic_pop3_auth.pl.in basic_pop3_auth || 
(/bin/rm -f -f basic_pop3_auth ; exit 1)
Making all in RADIUS
if ccache g++ -DHAVE_CONFIG_H  -I../../../.. -I../../../../include 
-I../../../../src  -I../../../include -I/usr/local/include
-I../../../../helpers/basic_auth/RADIUS-Wall -Wpointer-arith 
-Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT -g -O2 -MT 
basic_radius_auth.o -MD -MP -MF .deps/basic_radius_auth.Tpo -c -o 
basic_radius_auth.o ../../../../helpers/basic_auth/RADIUS/basic_radius_auth.cc; 
 then mv -f .deps/basic_radius_auth.Tpo .deps/basic_radius_auth.Po; else rm 
-f .deps/basic_radius_auth.Tpo; exit 1; fi
if ccache g++ -DHAVE_CONFIG_H  -I../../../.. -I../../../../include 
-I../../../../src  -I../../../include -I/usr/local/include
-I../../../../helpers/basic_auth/RADIUS-Wall -Wpointer-arith 
-Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT -g -O2 -MT radius-util.o 
-MD -MP -MF .deps/radius-util.Tpo -c -o radius-util.o 
../../../../helpers/basic_auth/RADIUS/radius-util.cc;  then mv -f 
.deps/radius-util.Tpo .deps/radius-util.Po; else rm -f 
.deps/radius-util.Tpo; exit 1; fi
/bin/sh ../../../libtool --tag=CXX --mode=link ccache g++ -Wall -Wpointer-arith 
-Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT  -g -O2  -g -o 
basic_radius_auth  basic_radius_auth.o  radius-util.o -L../../../lib -lmiscutil 
 ../../../compat/libcompat.la-lm 
libtool: link: ccache g++ -Wall -Wpointer-arith -Wwrite-strings -Wcomments 
-Werror -pipe -D_REENTRANT -g -O2 -g -o basic_radius_auth basic_radius_auth.o 
radius-util.o  
-Lhttp://build.squid-cache.org/job/3.HEAD-i386-OpenBSD/ws/btlayer-00-default/squid-3.HEAD-BZR/_build/lib
 -lmiscutil ../../../compat/.libs/libcompat.a -lm
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: vsprintf() is often misused, please use vsnprintf()
basic_radius_auth.o(.text+0x128): In function `main':
../../../../helpers/basic_auth/RADIUS/basic_radius_auth.cc:471: warning: 
strcpy() is almost always misused, please use strlcpy()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: strcat() is almost always misused, please use strlcat()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: sprintf() is often misused, please use snprintf()
Making all in fake
if ccache g++ -DHAVE_CONFIG_H  -I../../../.. -I../../../../include 
-I../../../../src  -I../../../include -I/usr/local/include   -Wall 
-Wpointer-arith -Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT -g -O2 
-MT fake.o -MD -MP -MF .deps/fake.Tpo -c -o fake.o 
../../../../helpers/basic_auth/fake/fake.cc;  then mv -f .deps/fake.Tpo 
.deps/fake.Po; else rm -f .deps/fake.Tpo; exit 1; fi
/bin/sh ../../../libtool --tag=CXX --mode=link ccache g++ -Wall -Wpointer-arith 
-Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT  -g -O2  -g -o 
basic_fake_auth  fake.o -L../../../lib -lmiscutil  ../../../compat/libcompat.la 
libtool: link: ccache g++ -Wall -Wpointer-arith -Wwrite-strings -Wcomments 
-Werror -pipe -D_REENTRANT -g -O2 -g -o basic_fake_auth fake.o  
-Lhttp://build.squid-cache.org/job/3.HEAD-i386-OpenBSD/ws/btlayer-00-default/squid-3.HEAD-BZR/_build/lib
 -lmiscutil ../../../compat/.libs/libcompat.a
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: vsprintf() is often misused, please use vsnprintf()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: strcpy() is almost always misused, please use strlcpy()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: strcat() is almost always misused, please use strlcat()
/usr/local/lib/gcc/i386-unknown-openbsd4.7/4.2.4/../../../libestdc++.so.11.0: 
warning: sprintf() is often misused, please use snprintf()
Making all in getpwnam
if ccache g++ -DHAVE_CONFIG_H  -I../../../.. -I../../../../include 
-I../../../../src  -I../../../include -I/usr/local/include   -Wall 
-Wpointer-arith -Wwrite-strings -Wcomments -Werror -pipe -D_REENTRANT -g -O2 
-MT basic_getpwnam_auth.o -MD -MP -MF .deps/basic_getpwnam_auth.Tpo -c -o 
basic_getpwnam_auth.o 
../../../../helpers/basic_auth/getpwnam/basic_getpwnam_auth.cc;  then mv -f 
.deps/basic_getpwnam_auth.Tpo .deps/basic_getpwnam_auth.Po; else rm -f 
.deps/basic_getpwnam_auth.Tpo; exit 1; fi
/bin/sh