Hello,

On 2014-07-02, 18:39:09, Willy Tarreau wrote:
> > BTW, if abns@ bind() fails during a "-sf" reload, then /tmp/test1.sock of 
> > the
> > old HAProxy instance is unlinked/unreachable and thus cannot accept new
> > connections. The new unix@ bind() succeeded, the ".tmp" got renamed, the 
> > ".bak"
> > was unlinked. So far so good. But when the abns@ bind() fails, then the 
> > whole
> > new HAProxy instance fails and leaves the old instance "degraded".
> > 
> > I do not know how to simply fix this.
> 
> That's a good point. We have no link()/unlink() on abstract sockets, so
> I don't see how we'll be able to temporarily rename a socket. Since this
> is linux-only, we can consider any os-specific trick available and see if
> one is satisfying (eg: shutdown(RD) followed by listen(), etc).

I was unable to make it work that way. I used the attached code in one
console, and in the other: 

strace -e trace=bind socat abstract-listen:test,unix-tightsocklen=0 stdio

I tried a few combinations of shutdown() / listen(), the ordering, ...,
but no luck.

> So what socat does prevents us from building binary addresses (eg: random
> addresses for internal communications). But, in practice, we're making names
> out of human-readable strings, we're not building addresses out of binary
> data, so I'd be tempted to think that it would make more sense to adopt
> socat's naming method instead of padding the remaining bytes with zeroes.
> 
> Still I feel concerned about future evolutions. I have a deep feeling that
> this is something we could regret sooner or later. Indeed, if we use strlen()
> over possibly binary contents to retrieve a socket address length, something
> tells me that we're sacrifying the ability to later extend this scheme to
> other usages.

Indeed. I wasn't happy with using strlen() either :).

> 
> > The second attached patch (haproxy_correct_abns_length.diff) seems to fix 
> > it.
> > No idea whether this is the right way to do it.
> 
> I've just found in socat's man that it supports both modes :
> 
>        unix-tightsocklen=[0|1]
>             On socket operations, pass a socket address length that does not
>               include the whole  struct  sockaddr_un record  but  (besides
>               other components)  only  the  relevant part of the filename or
>               abstract string.
>               Default is 1.
> 
> and indeed it works here :
> 
>   $ strace -s 200 -e trace=connect socat readline 
> abstract-connect:foo,unix-tightsocklen=0
>   connect(3, {sa_family=AF_FILE, path=@"foo"}, 110) = 0
> 
> So given that, I'd prefer to stay on the current scheme and document this
> way to interface with socat instead. It seems safer and more durable to me.
> What do you think ?

Oh, I didn't know socat had such an option until you mentioned it :).
Neat. Keeping the current scheme makes sense now.

> 
> > I can work around all of those problems by using plain old unix sockets
> > instead, but I like the idea of abstract namespace sockets :).
> 
> I like it as well, but you see, another concern I have is the fact that
> any other process -not just haproxy- could be bound to an abstract socket.
> While there are well-known ports for TCP/UDP services, there's no official
> registry of well-known abstract socket addresses and this is a problematic
> point. I suspect that we'll quickly come up with a complement which is a
> random address : we would generate a random address and try to bind. Then
> we would map each abstract name to that random address. It would solve all
> the communications issues within a group of processes belonging to the same
> config space.

Also with abstract sockets, we lack any access control (apart from the
apparent possibility of collisions). Any process can bind() / connect()
to any name.

> My gut feeling is that we should use file-system for anything system-wide
> (ie: socat to haproxy), as it's the only way to safely connect two ends. But
> we could use abstract sockets inside the same process or group of processes.
>
> An intermediate mechanism could be to have haproxy automatically prefix
> abstract sockets with the starting process' pid or with a short random.

But that would kill the possibility of two processes inside different
chroots to communicate efficiently (without some mount --bind tricks).

(I don't have any practical example of such a setup, though :))

> So I have applied patch #1 and not #2. Instead I think we'd rather continue
> to discuss the design choices and options here.

Thanks.

> Best regards,
> Willy

Best regards,

-- 
hodor

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <assert.h>
#include <unistd.h>

int main(int argc, char ** argv)
{
    int s, err, one=1;
    struct sockaddr_un sun;


    s = socket(AF_UNIX, SOCK_STREAM, 0);
    assert(s != -1);

    memset(&sun, 0, sizeof sun);
    sun.sun_family = AF_UNIX;
    strcpy(&sun.sun_path[1], "test");

    err = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    assert(err != -1);

    err = bind(s, &sun, sizeof sun);
    assert(err != -1);

    err = listen(s, 5);
    assert(err != -1);


    err = shutdown(s, SHUT_WR);
//    err = listen(s, 5);
    err = shutdown(s, SHUT_RD);

//    sun.sun_path[1] = 'r';
//    err = bind(s, &sun, sizeof sun);
//    assert(err != -1);


    pause();

    return 0;
}

Reply via email to