Re: Bug #882: Cannot manually log in to database.

Поиск
Список
Период
Сортировка
От Giles Lean
Тема Re: Bug #882: Cannot manually log in to database.
Дата
Msg-id 10193.1043464499@nemeton.com.au
обсуждение исходный текст
Ответ на Re: Bug #882: Cannot manually log in to database.  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: Bug #882: Cannot manually log in to database.  (Tom Lane <tgl@sss.pgh.pa.us>)
Re: Bug #882: Cannot manually log in to database.  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-bugs
Tom Lane <tgl@sss.pgh.pa.us> writes:
> Giles Lean <giles@nemeton.com.au> writes:
>
> >     utimes("/tmp/.s.PGSQL.5432", (const struct timeval *) 0);
>
> Hm, do you think that's portable?

Hm ... yes, actually I do.  I use it on HP-UX, and testing indicates
that it works on FreeBSD, Linux, NetBSD and Tru64 as well.

Thinking about it, a Unix domain socket has an entry in the filesystem
and thus an inode. utimes() operates on the inode so it makes sense to
me that this should Just Work.

While UNIX98 (aka the "Single Unix Standard, version 2") talks about a
"file" argument to utimes() it doesn't make any particular mention
about restrictions on what type of file, and the function needs to
work on some non-regular files such as device files to be useful.

> There is already code in the postmaster to touch the socket lock file
> every few minutes, so as to keep tmp-cleaners from zapping it.  (Or at
> least there once was; I can't find it right now.)  If we could do the
> same for the socket file it'd be really nice.  But I didn't think there
> was any portable way to update the mod timestamp on a socket.

I've done some testing today, and the test passed on everything I
tested it on:

    FreeBSD 4.7-RELEASE alpha
    HP-UX B.11.11 9000/800
    HP-UX B.11.22 ia64
    Linux 2.4.18-14 i686              # RedHat Linux 8.0
    Linux 2.4.18-mckinley-smp ia64    # Debian GNU/Linux 3.0
    NetBSD 1.6_STABLE i386
    OSF1 V4.0 alpha                   # Tru64
    OSF1 V5.1 alpha                   # Tru64

It's too hot here today to go outside but even so, that's enough
testing ...

I've attached the code I used.  It was considered to work if utimes()
didn't return an error and if the st_mtime value returned by stat()
changed:

   $ make socket_utimes
   cc -O2   -o socket_utimes socket_utimes.c
   $ ./socket_utimes socket
   utimes() successfully changed a Unix domain socket mtime.
   $ uname -srm
   NetBSD 1.6_STABLE i386

If utimes() works on the other supported platforms that have Unix
domain sockets perhaps we can put the /tmp cleaners to rest for good.

Anyone willing to test AIX, IRIX, MacOS X, Solaris, or SCO Unix?  I
don't expect the Windows ports with or without cygwin will support
Unix domain sockets, so they probably don't need testing. :-)

Regards,

Giles

P.S. http://www.testdrive.hp.com is great for quick portability
testing.  It was a Compaq program that HP has expanded since their
merger.  Highly recommended.
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    char *path;
    int sock_fd;
    struct sockaddr_un addr;
    struct stat sb_before;
    struct stat sb_after;

    if (argc != 2) {
        fprintf(stderr, "usage: socket_utimes path\n");
        exit(EXIT_FAILURE);
    }
    path = argv[1];

    sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sock_fd == -1) {
        fprintf(stderr, "socket: %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);

#ifndef SUN_LEN
#define SUN_LEN(su) \
    (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif

    if (bind(sock_fd, (struct sockaddr *) &addr, SUN_LEN(&addr)) == -1) {
        fprintf(stderr, "bind: %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

    if (stat(path, &sb_before) == -1) {
        fprintf(stderr, "stat: %s: %s\n", path, strerror(errno));
        (void) unlink(path);
        exit(EXIT_FAILURE);
    }

    sleep(2);

    if (utimes(path, (struct timeval *) 0) == -1) {
        fprintf(stderr, "utimes: %s: %s\n", path, strerror(errno));
        (void) unlink(path);
        exit(EXIT_FAILURE);
    }

    if (stat(path, &sb_after) == -1) {
        fprintf(stderr, "stat: %s: %s\n", path, strerror(errno));
        (void) unlink(path);
        exit(EXIT_FAILURE);
    }

    if (sb_before.st_mtime == sb_after.st_mtime) {
        printf("Oops: utimes() failed to change mtime\n");
        (void) unlink(path);
        exit(EXIT_FAILURE);
    }

    printf("utimes() successfully changed a Unix domain socket mtime.\n");
    (void) unlink(path);
    exit(EXIT_SUCCESS);
}





В списке pgsql-bugs по дате отправления:

Предыдущее
От: pgsql-bugs@postgresql.org
Дата:
Сообщение: Bug #886: jdbc "update row" can mess up other columns
Следующее
От: Tom Lane
Дата:
Сообщение: Re: Bug #882: Cannot manually log in to database.