Ticket #2038 (closed bug: fixed)

Opened 5 years ago

Last modified 5 years ago

System.Posix.Resource.setResourceLimit gives "setResourceLimit: invalid argument (Invalid argument)"

Reported by: slyfox Owned by: igloo
Priority: high Milestone: 6.8.3
Component: libraries/unix Version: 6.8.2
Keywords: regression, ffi, unix Cc: hackage.haskell.org@…
Operating System: Linux Architecture: x86
Type of failure: Difficulty: Unknown
Test Case: resourceLimit Blocked By:
Blocking: Related Tickets:

Description

GHC-6.6.1 worked correctly in setResourceLimit, GHC-6.8.2 gives me an error:

$ ./m 
m: setResourceLimit: invalid argument (Invalid argument)

A little exploration (strange rlim_max value). Seems to be a bug in haskell -> C type conversion.

$ strace -etrace=setrlimit ./m 
setrlimit(RLIMIT_CPU, {rlim_cur=3, rlim_max=0}) = -1 EINVAL (Invalid argument)
m: setResourceLimit: invalid argument (Invalid argument)

Code source:

import System.Exit              (exitWith, ExitCode(ExitSuccess))
import System.IO                (putStrLn)
import System.Posix.Resource

rlimit = ResourceLimit 3

f = do
    putStrLn "whoooooo"
    f
main = do
    setResourceLimit ResourceCPUTime (ResourceLimits rlimit rlimit)
    r <- getResourceLimit ResourceCPUTime
    let (ResourceLimit s) = softLimit r
    let (ResourceLimit h) = hardLimit r
    putStrLn $ show s
    putStrLn $ show h
    f
    exitWith ExitSuccess

Change History

Changed 5 years ago by slyfox

  • version changed from 6.8.1 to 6.8.2

Changed 5 years ago by igloo

  • priority changed from normal to high
  • difficulty set to Unknown
  • milestone set to 6.8.3

Thanks for the report. I can reproduce this on x86/Linux, but not amd64/Linux.

Changed 5 years ago by slyfox

  • component changed from Compiler to libraries/unix

After some exploration I've noticed: ./m binary calls setrlimit function (thanks to ltrace), but hsc2hs (in my config) generates code/offsets for setrlimit64 (because ghcautoconf.h defines:

#define _FILE_OFFSET_BITS 64

) In linux C function has name setrlimit64/getrlimit64 when this macrovar enabled. (I'm afraid there's many dual functions in x86: all file IO, etc.)

Unix package imports function by name:

ghc/libraries/unix/System/Posix/Resource.hsc:

foreign import ccall unsafe "setrlimit"                                                                                 
c_setrlimit :: CInt -> Ptr RLimit -> IO CInt

but include/sys/resource.h has follwong code:

#ifndef __USE_FILE_OFFSET64 // activated in features.h via _FILE_OFFSET_BITS   == 64
extern int getrlimit (__rlimit_resource_t __resource,
                      struct rlimit *__rlimits) __THROW;
#else
# ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (getrlimit, (__rlimit_resource_t __resource,
                                       struct rlimit *__rlimits), getrlimit64);
# else
#  define getrlimit getrlimit64
# endif
#endif
#ifdef __USE_LARGEFILE64
extern int getrlimit64 (__rlimit_resource_t __resource,
                        struct rlimit64 *__rlimits) __THROW;
#endif

The simplest way is to copy this ugly #ifdef into Resource.hsc. I think yet more portable solution.

Changed 5 years ago by slyfox

Code like this would look like:

-- strlimit{,64} is taken from C defines
foreign import ccall unsafe "#hsc2-mega-macro setrlimit" c_setrlimit :: CInt -> Ptr RLimit -> IO CInt

Simply grepping by /usr/include got some of funs:

./unistd.h:#  define lseek lseek64
./unistd.h:#   define pread pread64
./unistd.h:#   define pwrite pwrite64
./unistd.h:#   define truncate truncate64
./unistd.h:#   define ftruncate ftruncate64
./unistd.h:#   define lockf lockf64

./glob.h:# define glob glob64
./glob.h:# define globfree globfree64

./aio.h:#  define aio_read aio_read64
./aio.h:#  define aio_write aio_write64
./aio.h:#  define lio_listio lio_listio64
./aio.h:#  define aio_error aio_error64
./aio.h:#  define aio_return aio_return64
./aio.h:#  define aio_cancel aio_cancel64
./aio.h:#  define aio_suspend aio_suspend64
./aio.h:#  define aio_fsync aio_fsync64

./fcntl.h:#  define open open64
./fcntl.h:#  define lockf lockf64
./fcntl.h:#  define posix_fadvise posix_fadvise64
./fcntl.h:#  define posix_fallocate posix_fallocate64

./sys/mman.h:#  define mmap mmap64

./sys/statvfs.h:#  define statvfs statvfs64
./sys/statvfs.h:#  define fstatvfs fstatvfs64
./sys/statfs.h:#  define statfs statfs64
./sys/statfs.h:#  define fstatfs fstatfs64

./dirent.h:#  define readdir readdir64
./dirent.h:#   define readdir_r readdir64_r
./dirent.h:#   define scandir scandir64

./stdlib.h:#   define mkstemp mkstemp64

Is there/can be implemented such functionality hsc2hs? Thanks!

Changed 5 years ago by igloo

See also #2093

Changed 5 years ago by igloo

  • owner set to igloo

Changed 5 years ago by Eelis-

  • cc hackage.haskell.org@… added

As requested in the  Release Plans message, I'm hereby expressing that this bug is very important to me. It pretty much makes  geordi completely unusable on x86-32.

Changed 5 years ago by igloo

  • status changed from new to closed
  • testcase set to resourceLimit
  • resolution set to fixed

I've fixed this for getrlimit, setrlimit and mkstemp; I didn't find any other problematic cases.

The fix is in both the HEAD and the 6.8 branch.

Note: See TracTickets for help on using tickets.