public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* bug in pipe() and pipe2()
@ 2011-06-29 21:30 Eric Blake
  2011-06-30  9:39 ` Corinna Vinschen
  0 siblings, 1 reply; 4+ messages in thread
From: Eric Blake @ 2011-06-29 21:30 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 1110 bytes --]

I was testing the behavior when pipe() fails, in order to propose an
update to POSIX wording: http://austingroupbugs.net/view.php?id=467

However, cygwin's pipe implementation dumps core when it runs out of
fds, so I could not definitively state whether cygwin properly leaves
the fd array unchanged on error, the way Linux does.  According to a gdb
run and while using stock 1.7.9 cygwin1.dll, the crash is in
fhandler_pipe::create().

#define _POSIX_C_SOURCE 200811L
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int
main (int argc, char **argv)
{
  int i = 0;
  while (1) {
    int fd[2] = {-2,-3};
    int err = pipe(fd);
    if (err) {
      printf ("iteration %d, pipe returned %d errno %d %s, fds %d %d\n",
          i, err, errno, strerror(errno), fd[0], fd[1]);
      break;
    }
    i++;
  }
  return 0;
}

Expected behavior is EMFILE and fd unchanged, after however many
iterations it takes to reach the ulimit on max fd.

-- 
Eric Blake   eblake@redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: bug in pipe() and pipe2()
  2011-06-29 21:30 bug in pipe() and pipe2() Eric Blake
@ 2011-06-30  9:39 ` Corinna Vinschen
  2011-06-30 11:51   ` Ryan Johnson
  0 siblings, 1 reply; 4+ messages in thread
From: Corinna Vinschen @ 2011-06-30  9:39 UTC (permalink / raw)
  To: cygwin

On Jun 29 15:30, Eric Blake wrote:
> I was testing the behavior when pipe() fails, in order to propose an
> update to POSIX wording: http://austingroupbugs.net/view.php?id=467
> 
> However, cygwin's pipe implementation dumps core when it runs out of
> fds, [...]
> Expected behavior is EMFILE and fd unchanged, after however many
> iterations it takes to reach the ulimit on max fd.

The problem is that Cygwin uses a placement new operator to allocate
new fhandlers.  This type of new operator calls the constructor even
if the placement pointer is NULL.  This in turn crashes in a rather
obvious way.

Since we need the placement new for fhandlers to make sure they are
allocated on the cygheap, and since there is no such operator which
only calls the constructor, I only see a very ugly workaround for this
problem.

I checked it in, together with two more fixes to avoid a crash.
If somebody has a better solution, feel free to mention it.


Thanks for the report,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: bug in pipe() and pipe2()
  2011-06-30  9:39 ` Corinna Vinschen
@ 2011-06-30 11:51   ` Ryan Johnson
  2011-06-30 14:07     ` Corinna Vinschen
  0 siblings, 1 reply; 4+ messages in thread
From: Ryan Johnson @ 2011-06-30 11:51 UTC (permalink / raw)
  To: cygwin

On 30/06/2011 5:38 AM, Corinna Vinschen wrote:
> On Jun 29 15:30, Eric Blake wrote:
>> I was testing the behavior when pipe() fails, in order to propose an
>> update to POSIX wording: http://austingroupbugs.net/view.php?id=467
>>
>> However, cygwin's pipe implementation dumps core when it runs out of
>> fds, [...]
>> Expected behavior is EMFILE and fd unchanged, after however many
>> iterations it takes to reach the ulimit on max fd.
> The problem is that Cygwin uses a placement new operator to allocate
> new fhandlers.  This type of new operator calls the constructor even
> if the placement pointer is NULL.  This in turn crashes in a rather
> obvious way.
>
> Since we need the placement new for fhandlers to make sure they are
> allocated on the cygheap, and since there is no such operator which
> only calls the constructor, I only see a very ugly workaround for this
> problem.
>
> I checked it in, together with two more fixes to avoid a crash.
> If somebody has a better solution, feel free to mention it.
If you don't mind using a couple of gcc extensions (we are a gcc-only 
shop, right?):

#define cnew(name, ...) ({                                              \
             void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof 
(name)); \
             ptr? new(ptr) name(__VA_ARGS__) : NULL;                     \
         })

The macro's usage would change to look like a normal function call:

fhandler_base *fh = cnew(fhandler_nodevice);

You just need to check fh != NULL afterward. If the ctor for 
fhandler_nodevice took an argument 'x' it would follow as additional 
args to the cnew macro, rather than as an additional set of parens:

fhandler_base *fh = cnew(fhandler_nodevice, x);

Regards,
Ryan

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: bug in pipe() and pipe2()
  2011-06-30 11:51   ` Ryan Johnson
@ 2011-06-30 14:07     ` Corinna Vinschen
  0 siblings, 0 replies; 4+ messages in thread
From: Corinna Vinschen @ 2011-06-30 14:07 UTC (permalink / raw)
  To: cygwin

On Jun 30 07:50, Ryan Johnson wrote:
> On 30/06/2011 5:38 AM, Corinna Vinschen wrote:
> > I only see a very ugly workaround for this
> >problem.
> >
> >I checked it in, together with two more fixes to avoid a crash.
> >If somebody has a better solution, feel free to mention it.
> If you don't mind using a couple of gcc extensions (we are a
> gcc-only shop, right?):

Indeed.

> #define cnew(name, ...) ({                                              \
>             void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof
> (name)); \
>             ptr? new(ptr) name(__VA_ARGS__) : NULL;                     \
>         })
> 
> The macro's usage would change to look like a normal function call:
> 
> fhandler_base *fh = cnew(fhandler_nodevice);
> 
> You just need to check fh != NULL afterward. If the ctor for
> fhandler_nodevice took an argument 'x' it would follow as additional
> args to the cnew macro, rather than as an additional set of parens:
> 
> fhandler_base *fh = cnew(fhandler_nodevice, x);

Cool.  Thanks a lot.  I tried some ({ ... }) expression as well but
apparently gave up too early.  I applied your change since it's much
cleaner than my ugly hack.


Thanks again,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-06-30 14:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-29 21:30 bug in pipe() and pipe2() Eric Blake
2011-06-30  9:39 ` Corinna Vinschen
2011-06-30 11:51   ` Ryan Johnson
2011-06-30 14:07     ` Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).