Re: pflocal socket bug

2015-09-10 Thread Samuel Thibault
Hello,

Thanks for the detailed description and testcase!  I could fix it, this
case was actually apparently completely untested: reference counting was
never reaching zero, and thus the sock never actually shut down.

SAmuel



Re: [PATCH] Install port-deref-deferred.h header for ports.h

2015-09-10 Thread Samuel Thibault
James Clarke, le Thu 10 Sep 2015 11:59:04 +0100, a écrit :
> * libports/Makefile (installhdrs): Add port-deref-deferred.h for ports.h

Applied, thanks!

Samuel



[PATCH] Install port-deref-deferred.h header for ports.h

2015-09-10 Thread James Clarke
* libports/Makefile (installhdrs): Add port-deref-deferred.h for ports.h
---
 libports/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libports/Makefile b/libports/Makefile
index b8b82ee..af881f8 100644
--- a/libports/Makefile
+++ b/libports/Makefile
@@ -38,7 +38,7 @@ SRCS = create-bucket.c create-class.c \
  claim-right.c transfer-right.c create-port-noinstall.c create-internal.c \
  interrupted.c extern-inline.c port-deref-deferred.c
 
-installhdrs = ports.h
+installhdrs = ports.h port-deref-deferred.h
 
 HURDLIBS= ihash
 LDLIBS += -lpthread
-- 
2.5.1




pflocal socket bug

2015-09-10 Thread Svante Signell
Hi,

Looking into the socklog package test errors a bug was found in the
pflocal socket implementation, specifically in connect():
1)
PID1: create a local named socket using a server to receive data
PID2: connect to that socket with a client to send data
everything is fine :)

Terminal1:
./test_socket_server.DGRAM 
test_socket_server:main(): Domain = AF_UNIX, Type = SOCK_DGRAM
test_socket_server:main(): Removing old socket: 'test_socket'
test_socket_server:socket_unix(): socket() socket_fd = 3
test_socket_server:read_socket(): Waiting for incoming connections...

Terminal2:
./test_socket_client.DGRAM 
test_socket_client:main(): Domain = AF_UNIX, Type = SOCK_DGRAM
test_socket_client:main(): socket_name = 'test_socket'
test_socket_client:write_socket(): connect(): err = '(os/kern)
successful'
test_socket_client:write_socket(): send() err = '(os/kern) successful'

Terminal1:
test_socket_server:read_socket(): read() Message = 'Testing,
testing, ...'

2) kill $PID1 to leave the socket behind
PID2: connect to that socket with a client to send data
On hurd this is not detected:
/test_socket_client.DGRAM 
test_socket_client:main(): Domain = AF_UNIX, Type = SOCK_DGRAM
test_socket_client:main(): socket_name = 'test_socket'
test_socket_client:write_socket(): connect(): err = '(os/kern)
successful' <-- BUG IS HERE
test_socket_client:write_socket(): send() err = '(os/kern) successful'

Expected output e.g. on Linux (or with AF_INET):
./test_socket_client.DGRAM
test_socket_client:main(): Domain = AF_UNIX, Type = SOCK_DGRAM
test_socket_client:main(): socket_name = 'test_socket'
test_socket_client:write_socket(): connect(): err = 'Connection refused'
<-- correct ECONNREFUSED is returned
test_socket_client:write_socket(): connect(): Connection refused
test_socket_client:main(): write_socket() SOCK_DGRAM: Connection refused

Programs are attached to cover the following cases selected in defs.inc:
AF_UNIX+SOCK_DGRAM, AF_UNIX+SOCK_STREAM (pflocal is buggy)
AF_INET+SOCK_DGRAM, AF_INET+SOCK_STREAM (pfinet is fine)

I've tried to find out how to detect that the socket server is gone but
not found a solution yet.

Functions tried in pflocal/sock.c:
pipe_acquire_reader(pipe): modifies the reference count and locking
problems
pipe_acquire_writer(pipe): modifies the reference count and locking
problems
pipe_is_readable(pipe, 0/1): always returns false
pipe_wait_readable(pipe, 1, 0/1): always returns EAGAIN, setting noblock
to 0 makes the box freeze :(
pipe_wait_writable(pipe, 0/1): Always returns 0 since
pipe->readable(pipe, 1)=0 and pipe->write_limit=16384 (another bug?)

The test calls were placed in the function: void connect() planned to
return an error code instead.

Hopefully the problem is described detailed enough.

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

#include "defs.inc"

#ifdef USE_SOCK_STREAM
#define type SOCK_STREAM
#else
#define type SOCK_DGRAM
#endif

/* FIXME: Support AF_INET */
#ifdef USE_AF_UNIX
#define domain AF_UNIX
#else
#define domain AF_INET
#endif

#define SOCKET_NAME "test_socket"
#define DATA "Testing, testing, ..."

int write_socket(const char* socket_name) {
  int err = 0, socket_fd, write_size;
#ifdef USE_AF_UNIX
  struct sockaddr_un server;
  int c = sizeof(struct sockaddr_un);
#else
  struct sockaddr_in server;
  int c = sizeof(struct sockaddr_in);
#endif

  /* Create socket */
  socket_fd = socket (domain, type, 0);
  if (socket_fd == -1)
{
  perror("test_socket_client:write_socket(): socket()");
  return -1;
}
#ifdef USE_AF_UNIX
  server.sun_family = domain;
  strncpy (server.sun_path, socket_name, sizeof(server.sun_path));
#else
  server.sin_family = domain;
  server.sin_addr.s_addr = inet_addr("127.0.0.1");
  server.sin_port = htons(  );
#endif

  /* Connect to socket_fd */
  err = connect (socket_fd, (struct sockaddr *)&server, c);
  printf("test_socket_client:write_socket(): connect(): err = '%s'\n", strerror(errno));
  if (err) {
close(socket_fd);
#ifdef EDESTADDRREQ
if (errno == EDESTADDRREQ) errno = ECONNREFUSED;
#endif
perror("test_socket_client:write_socket(): connect()");
return err;
  }
#if 0
  write_size = write (socket_fd, DATA, sizeof(DATA));
  printf("test_socket_client:write_socket(): write(): err = '%s'\n", strerror(errno));
#else
  write_size = send (socket_fd, DATA, sizeof(DATA), 0);
  printf("test_socket_client:write_socket(): send() err = '%s'\n", strerror(errno));
#endif
  if (write_size == -1)
{
#ifdef USE_SOCK_STREAM
  perror("test_socket_client:write_socket(): write(): Sending on stream socket");
#else
  perror("test_socket_client:write_socket(): write(): Sending on datagram socket");
#endif
  close(socket_fd);
  return err;
}

  close(socket_fd);
  return err;
}

int main(void) {
  const char* socket_name = SOCKET_NAME;
  int err = 0;

  printf ("test_socket_client:main(): Domain = %s, Type = %s\n", (domain == AF_UNIX) ? "AF_UNIX": "AF_INET", (type == S