Opened 9 years ago

Closed 9 years ago

#5060 closed bug (invalid)

iteratee: epollControl: permission denied (Operation not permitted)

Reported by: pacak Owned by:
Priority: high Milestone: 7.2.1
Component: libraries/base Version: 7.0.3
Keywords: Cc: johan.tibell@…, jwlato@…, tkn.akio@…
Operating System: Linux Architecture: x86_64 (amd64)
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by igloo)

If you run this ticket as literate haskell program it works fine when

  1. executed via ghci/runhaskell in ghc 6.12.3
  2. executed as compiled file in both ghc 6.12.3 and 7.0.2/7.0.3

and it fails with a message " epollControl: permission denied (Operation not permitted)" when executed via runhaskell in ghc 7.0.2/7.0.3

> import Data.Iteratee
> import Data.Iteratee.IO
> import Data.Iteratee.Char

> main = fileDriver printLines "/etc/passwd"

some logs are attached

Attachments (1)

run.log (6.0 KB) - added by pacak 9 years ago.

Download all attachments as: .zip

Change History (20)

Changed 9 years ago by pacak

Attachment: run.log added

comment:1 Changed 9 years ago by tibbe

Cc: johan.tibell@… added
Component: CompilerGHCi

To summarize: the bug only shows up in ghci on GHC 7.0.{1,2,3}.

comment:2 Changed 9 years ago by pacak

Actually example could be simplified up to this:

import System.Posix.IO
import GHC.Conc

main = do
    fd <- openFd "/etc/passwd" ReadOnly Nothing defaultFileFlags
    threadWaitRead fd        -- the big bang happens right here.
    closeFd fd

comment:3 Changed 9 years ago by tibbe

I will take as soon as I have time, probably some time next week. Thanks for simplifying the test case.

comment:4 Changed 9 years ago by pacak

strace shows that compiled version uses select

open("/etc/passwd", O_RDONLY)           = 3
select(4, [3], [], NULL, {134, 217727}) = 1 (in [3], left {134, 217725})

while ghci version uses epoll

open("/etc/passwd", O_RDONLY) = 7
epoll_ctl(3, EPOLL_CTL_ADD, 7, {EPOLLIN, {u32=7, u64=12117878556374073351}}) = -1 EPERM (Operation not permitted)

comment:5 in reply to:  4 ; Changed 9 years ago by tibbe

Replying to pacak:

strace shows that compiled version uses select

open("/etc/passwd", O_RDONLY)           = 3
select(4, [3], [], NULL, {134, 217727}) = 1 (in [3], left {134, 217725})

while ghci version uses epoll

open("/etc/passwd", O_RDONLY) = 7
epoll_ctl(3, EPOLL_CTL_ADD, 7, {EPOLLIN, {u32=7, u64=12117878556374073351}}) = -1 EPERM (Operation not permitted)

That's odd. The I/O manager should be using epoll on Linux.

comment:6 in reply to:  5 Changed 9 years ago by pacak

Replying to tibbe:

Replying to pacak: That's odd. The I/O manager should be using epoll on Linux.

It should. But if it really used it - iteratee would be completly broken in all regular file operations. It uses the same interface to poll fd for data. This works for sockets and stuff but fails for regular files:

#include <sys/epoll.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>


int main(int argc, char *argv[]) {
int fd = open("/etc/passwd", O_RDONLY);

int efd = epoll_create(5);
struct epoll_event ev = { 0, { 0 } };
ev.events = EPOLLOUT;
ev.data.fd = fd;
if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) < 0) {
perror("Failed to add fd to event set");
}
return 0;
}

It seems, that they do not support poll at all.

comment:7 Changed 9 years ago by jwlato

FWIW, the bug isn't present on OS X (10.6).

comment:8 Changed 9 years ago by jwlato

Cc: jwlato@… added

comment:9 Changed 9 years ago by akio

Cc: tkn.akio@… added
Component: GHCiRuntime System

I can also reproduce the failure with a compiled program linked with -threaded.

comment:10 Changed 9 years ago by simonmar

Component: Runtime Systemlibraries/base

The IO manager is part of the base package, not the RTS.

comment:11 Changed 9 years ago by igloo

Description: modified (diff)

comment:12 Changed 9 years ago by igloo

Description: modified (diff)

comment:13 in reply to:  3 Changed 9 years ago by igloo

Milestone: 7.2.1
Owner: set to johan.tibell@…
Priority: normalhigh

Replying to tibbe:

I will take as soon as I have time, probably some time next week.

Thanks!

comment:14 Changed 9 years ago by tibbe

To make it clear, the issue has nothing to do with ghci per say. It shows up whenever we run with the threaded RTS, which ghci does by default but programs compiled with ghc do not.

comment:16 Changed 9 years ago by bos

This is more or less a bug in the iteratee library. The pattern that users of threadWaitRead and threadWaitWrite must follow is to try an IO operation, and only wait if it returns with EWOULDBLOCK. I assume that the iteratee library is not following this convention.

Now admittedly you can only deduce this convention by reading existing code, as it's not documented, so I'm not surprised that it would arise.

comment:17 Changed 9 years ago by tibbe

Note that there's currently no good way to do async file I/O. Not with the old or new I/O manager. epoll makes this more clear by throwing the error you're seeing, while select/poll will just silently accept the file descriptor.

As for the iteratee library implementation, I recommend just making blocking read/write calls. Given the way that GHC implements (safe) foreign calls GHC should reuse OS threads from its thread pool to make the calls.

The only thing we can fix at the moment is the documentation of Control.Concurrent.threadWait*.

comment:18 Changed 9 years ago by tibbe

Owner: johan.tibell@… deleted

comment:19 Changed 9 years ago by simonmar

Resolution: invalid
Status: newclosed

Thanks for looking into this folks. Based on the discussion I'm closing this as not a bug; please re-open if that's not correct.

Note: See TracTickets for help on using tickets.