Coder Social home page Coder Social logo

unix's Introduction

The unix Package Hackage GitHub Build Status

See unix on Hackage for more information.

Installing from Git

To build this package using Cabal directly from Git, you must run autoreconf -i before the usual Cabal build steps (cabal {configure,build,install}). The program autoreconf is part of GNU autoconf. There is no need to run the configure script: cabal configure will do this for you.

unix's People

Contributors

andreasabel avatar angerman avatar batterseapower avatar bgamari avatar bodigrim avatar bos avatar dependabot[bot] avatar emilypi avatar erikd avatar ezyang avatar favonia avatar glguy avatar hasufell avatar hs-viktor avatar hvr avatar igfoo avatar jgoerzen avatar kgardas avatar luispedro avatar mkilian avatar mmhat avatar nh2 avatar nicolast avatar pcapriotti avatar phadej avatar redneb avatar ryanglscott avatar simonmar avatar terrorjack avatar thomie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unix's Issues

Can you please add interruptibleGetAnyProcessStatus functionality?

Hello,

I am wondering if you could add functionality to let getAnyProcessStatus to continue processing after an interrupt was received. This is closer to the waitpid() functionality.

diff --git a/System/Posix/Process/Common.hsc b/System/Posix/Process/Common.hsc
index 66e0d20..c764636 100644
--- a/System/Posix/Process/Common.hsc
+++ b/System/Posix/Process/Common.hsc
@@ -61,6 +61,7 @@ module System.Posix.Process.Common (
     getProcessStatus,
     getAnyProcessStatus,
     getGroupProcessStatus,
+    interruptibleGetAnyProcessStatus,

     -- ** Deprecated
     createProcessGroup,
@@ -375,6 +376,33 @@ getGroupProcessStatus block stopped pgid =
 getAnyProcessStatus :: Bool -> Bool -> IO (Maybe (ProcessID, ProcessStatus))
 getAnyProcessStatus block stopped = getGroupProcessStatus block stopped 1

+
+interruptibleGetGroupProcessStatus :: Bool
+                      -> Bool
+                      -> ProcessGroupID
+                      -> IO (Maybe (ProcessID, ProcessStatus))
+interruptibleGetGroupProcessStatus block stopped pgid =
+  alloca $ \wstatp -> do
+    pid <- c_waitpid (-pgid) wstatp (waitOptions block stopped)
+    case pid of
+      0  -> return Nothing
+      -1 -> return Nothing
+      _  -> do ps <- readWaitStatus wstatp
+               return (Just (pid, ps))
+
+-- | @'getAnyProcessStatus' blk stopped@ calls @waitpid@, returning
+--   @'Just' (pid, tc)@, the 'ProcessID' and 'ProcessStatus' for any
+--   child process if a child process has exited, or 'Nothing' if
+--   there are child processes but none have exited or if waitpid()
+--   returns -1.
+--
+--   If @blk@ is 'False', then @WNOHANG@ is set in the options for
+--   @waitpid@, otherwise not.  If @stopped@ is 'True', then
+--   @WUNTRACED@ is set in the options for @waitpid@, otherwise not.
+interruptibleGetAnyProcessStatus :: Bool -> Bool -> IO (Maybe (ProcessID, ProcessStatus))
+interruptibleGetAnyProcessStatus block stopped =
+ interruptibleGetGroupProcessStatus block stopped 1
+
 waitOptions :: Bool -> Bool -> CInt
 --             block   stopped
 waitOptions False False = (#const WNOHANG)

Thanks
Joe

`readdir_r` is deprecated

Building revision 40820da on Debian Testing I get:

cbits/HsUnix.c: In function ‘__hscore_readdir’:

cbits/HsUnix.c:64:3: error:
     warning: ‘readdir_r’ is deprecated [-Wdeprecated-declarations]
       res = readdir_r(dirPtr, p, pDirEnt);
       ^~~

In file included from include/HsUnix.h:71:0: error:
    0,
                     from cbits/HsUnix.c:9:

According to the man page:

This function is deprecated; use readdir(3) instead.

The readdir_r() function was invented as a reentrant version of readdir(3). It reads the next directory entry from the directory stream dirp, and returns it in the caller-allocated buffer pointed to by entry.

It is expected that a future version of POSIX.1 will make readdir_r() obsolete, and require that readdir() be thread-safe when concurrently employed on different directory streams.

Since the implementation already has #if HAVE_READDIR_R the fix mostly involves detecting whether readdir_r is deprecated or not and setting HAVE_READDIR_R appropriately.

Ghc 8.0.2

base-4.9.1.0

System/Posix/Process/Internals.hs:12:18: error:
    Module ‘GHC.Conc’ does not export ‘Signal’

time-1.7 is released

time-1.7 is released. Would you check if it builds OK, and update .cabal file?

Can you please add sigwait() of signal.h?

Hello,

Wondering if you could please add the haskell interface to sigwait() of signal.h?

diff --git a/System/Posix/Signals.hsc b/System/Posix/Signals.hsc
index d4c6d51..3ea400a 100644
--- a/System/Posix/Signals.hsc
+++ b/System/Posix/Signals.hsc
@@ -88,6 +88,7 @@ module System.Posix.Signals (
   getPendingSignals,
 #ifndef cygwin32_HOST_OS
   awaitSignal,
+  signalWait,
 #endif

 #ifdef __GLASGOW_HASKELL__
@@ -605,6 +606,24 @@ awaitSignal maybe_sigset = do

 foreign import ccall unsafe "sigsuspend"
   c_sigsuspend :: Ptr CSigset -> IO CInt
+
+signalWait :: Maybe SignalSet -> IO (Maybe Signal)
+signalWait maybe_sigset = do
+  fp <- case maybe_sigset of
+          Nothing -> do SignalSet fp <- getSignalMask; return fp
+          Just (SignalSet fp) -> return fp
+  withForeignPtr fp $ \p -> do
+    alloca $ \signalPtr -> do
+        v <- c_sigwait p signalPtr
+        case v of
+          0  -> do sig <- peek signalPtr
+                   return (Just sig)
+          -- on error, sigwait returns EINVAL: set contains
+          --  an invalid signal number
+          _  -> return Nothing
+
+foreign import ccall unsafe "sigwait"
+  c_sigwait :: Ptr CSigset -> Ptr CInt -> IO CInt
 #endif

 #ifdef __HUGS__

Thanks
Joe

SafeHaskell warnings

@dterei,

I currently see the following warnings even after having merged #27:

    ‘System.Posix.IO.Common’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.DynamicLinker.Common’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Directory.Common’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Error’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.ByteString.FilePath’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.DynamicLinker.ByteString’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Terminal.ByteString’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Process.ByteString’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Env.ByteString’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Files.ByteString’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.DynamicLinker’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.DynamicLinker.Module.ByteString’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Semaphore’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Resource’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Time’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Terminal’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Process’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Unistd’ is marked as Trustworthy but has been inferred as safe!
    ‘System.Posix.Files’ is marked as Trustworthy but has been inferred as safe!

Also, what's the motivation for disabling that warning in one of the modules like so

#ifdef __GLASGOW_HASKELL__
 {-# LANGUAGE Trustworthy #-}
+#if __GLASGOW_HASKELL__ >= 709
+{-# OPTIONS_GHC -fno-warn-trustworthy-safe #-}
+#endif
 #endif

?

Misleading error messages in `rename`

The rename function always mentions the first argument even if the issue is with the second one. For example:

rename "file.txt" "directory-which-does-not-exist/file.txt"

if file.txt exists, but directory-which-does-not-exist does not, the error message will say:

file.txt: rename: does not exist (No such file or directory)

export System.Posix.Directory.Common

Without DirStream, if you wish to do a deep traversal of a directory structure, it's necessary to stat everything in order to determine if it's a sub-directory (and needs to be descended into) or a regular file. This imposes a significant performance penalty (see https://github.com/JohnLato/posix-paths for benchmarks).

I don't think there's any reason this module can't be exported in its entirety.

safe vs. unsafe foreign imports

Hi,

I'm a bit surprised that various I/O (in the filesystem sense, not Haskell IO) functions are imported as unsafe. While they won't call back to Haskell, depeding on which filesystem they talk to, they can take arbitrary amounts of time, blocking an execution context for this entire duration.

Would it make sense to also have "safe" version of the functions, for the case when performance is less of an issue compared to safety? Would it make sense to at least document that they are imported unsafe?

For the record, I've run a simple benchmark comparing "chmod" performance on various local and remote filesystems and the difference between unsafe and safe is between 10% slower (nfs) to 25% slower (local real filesystems) to 30% (tmpfs). So there is a performance hit indeed.

handleToFd leaks memory

On unix-2.6.0.1 with GHC 7.6.3 the following program leaks memory very fast:

import Control.Monad
import System.IO
import System.IO.Error
import System.Posix.IO
import System.Posix.Types

test :: IO ()
test = do
  let path = "/tmp/leak-test"
  handle <- openFile path WriteMode
  putStrLn $ "Opened file " ++ path
  fd <- handleToFd handle
  putStrLn $ "Converted to handle " ++ path
  _ <- tryIOError $ closeFd fd
  putStrLn $ "Closed file " ++ path

main = forever test

This is only due to handleToFd. Opening a file directly using openFd doesn't leak.

isSymbolicLink returning false for a symlink in readonly btrfs subvolume

import System.Posix.Files

do
    f <- getFileStatus "/media/miguel/backup/backups/@home/@home-2015-11-10-14:00/miguel/log/Atalho para hugefscheck.log"
    print $ isSymbolicLink f
    print $ isRegularFile f
    print $ isDirectory f

False
True
False
stat "/media/miguel/backup/backups/@home/@home-2015-11-10-14:00/miguel/log/Atalho para hugefscheck.log"
  File: '/media/miguel/backup/backups/@home/@home-2015-11-10-14:00/miguel/log/Atalho para hugefscheck.log' -> '/home/miguel/log/hugefscheck.log'
  Size: 32        	Blocks: 8          IO Block: 4096   ligação simbólica
Device: 74h/116d	Inode: 348651      Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/  miguel)   Gid: ( 1000/  miguel)
...
 Birth: -

Is this a bug ?

getLock unexpectedly can clear an existing lock belonging to a process

I have a program that opens two different Fds to the same file, uses setLock on the first Fd, and then getLock on the second Fd. Once the getLock is done, the program no longer has a lock set on the file. This is with unix 2.7.0.1 and ghc 7.10.1.

This is very surprising (and is a testcase from stumbling over this problem in the wild), and I don't see behavior like this when I write a C program that does the same thing using fcntl F_SETLK and F_GETLK.

I'll paste my test program at the end of this bug report. The way to use it is open 2 terminals. In the first, run "./test setLock getLock". Then in the second, run "./test setLock" and see that it successfully sets the lock; the first process lost its lock on the file. If you instead run "./test setLock" in both terminals, it behaves as expected with the first process taking the lock so the second fails to take it.

import System.Posix.IO
import System.IO
import System.Environment

main = do
     mapM_ go =<< getArgs
     getLine

go "setLock" = do
    writeFile lck ""
    fd <- openFd lck ReadWrite Nothing defaultFileFlags
    print ("opened lock fd", fd)
    setLock fd (WriteLock, AbsoluteSeek, 0, 0)
    print ("setLock")
go "getLock" = do
    checkfd <- openFd lck ReadOnly Nothing defaultFileFlags
    print ("opened lock check fd", checkfd)
    ret <- getLock checkfd (ReadLock, AbsoluteSeek, 0, 0)
    case ret of
        Nothing -> print "getLock indicates the file is not locked"
        Just (pid, fl) -> print ("getLock detected lock by pid", pid)
    closeFd checkfd
lck = "locktest"

cfmakeraw

Would be helpful to have cfmakeraw(3) exported from System.Posix.Terminal.

It is needed when eg, writing a haskell program that works similarly to script.

I emulated cfmakeraw in my code like this:

                    as `withoutMode` IgnoreBreak
                        `withoutMode` InterruptOnBreak
                        `withoutMode` CheckParity
                        `withoutMode` StripHighBit
                        `withoutMode` MapLFtoCR
                        `withoutMode` IgnoreCR
                        `withoutMode` MapCRtoLF
                        `withoutMode` StartStopOutput
                        `withoutMode` ProcessOutput
                        `withoutMode` EnableEcho
                        `withoutMode` EchoLF
                        `withoutMode` ProcessInput
                        `withoutMode` KeyboardInterrupts
                        `withoutMode` ExtendedFunctions
                        `withoutMode` EnableParity

That was tedious to come up with, and it doesn't include the CSIZE setting that cfmakeraw does. And it may be that some unix has a cfmakeraw that differs in some subtle way, perhaps unsetting an OS-specific extension, in which case my haskell emulation would be buggy.

getPathVar fails for large files

Joeys reports at http://bugs.debian.org/773821:

import System.Posix.Files
import Control.Exception
import Foreign.C.Types
main = print =<< (try (getPathVar "." FileNameLimit) :: IO (Either IOException CLong))

This program can fail on a system with a large disk:

Left .: getPathVar: failed (Value too large for defined data type)

statfs(".", 0xffa8ad50)                 = -1 EOVERFLOW (Value too large for defined data type)

The problem is, getPathVar is using statfs, not statfs64.

Here's a C program that uses statfs64:

#define _LARGEFILE64_SOURCE 1
#include <sys/vfs.h>
#include <stdio.h>

main () {
        struct statfs64 buf;
        statfs64(".", &buf);
        printf("%li\n", buf.f_namelen);
}

And strace shows just how large some of the fields are, which is why
statfs() overflows.

statfs64(".", 84, {f_type=0x2fc12fc1, f_bsize=131072, f_blocks=67107265, f_bfree=66904371, f_bavail=66904371, f_files=17127878964, f_ffree=17127519173, f_fsid={-676822403, 15770009}, f_namelen=255, f_frsize=131072, f_flags=4128}) = 0

An added problem is that getPathVar is implemented using pathconf,
rather than using statfs directly. It seems that setting _LARGEFILE64_SOURCE
does not cause pathconf to use statfs64. This may be a glibc bug.

configure is broken

Commit b06446edd4753f964a46d27ddae864fad97adc13 has changed the semantics of configure that it now fails to properly detect if fdatasync(2) is available on the given platform. For more details, please see ticket #11137 of GHC.

accessTimeHiRes / modificationTimeHiRes / statusChangeTimeHiRes do not return subsecond precision on OS X

Hi,

I'm using unix 2.7.2.0 on OS X 10.11.5, Stack is version 1.0.4.3 x86_64, and ghc version 7.10.3. I'm finding that despite the autogenerated include/HsUnixConfig.h including

#define HAVE_STRUCT_STAT_ST_ATIMESPEC 1
#define HAVE_STRUCT_STAT_ST_CTIMESPEC 1
#define HAVE_STRUCT_STAT_ST_MTIMESPEC 1

I'm getting results like:

> statusChangeTimeHiRes <$> getFileStatus "/tmp" 
1466637634s

When I manually run hsc2hs on a checkout of master, the produced code looks like:

accessTimeHiRes (FileStatus stat) =
  unsafePerformIO $ withForeignPtr stat $ \stat_ptr -> do
    sec  <- ((\hsc_ptr -> peekByteOff hsc_ptr 32)) stat_ptr :: IO EpochTime
{-# LINE 292 "System/Posix/Files/Common.hsc" #-}

{-# LINE 296 "System/Posix/Files/Common.hsc" #-}
    nsec <- ((\hsc_ptr -> peekByteOff hsc_ptr 40)) stat_ptr :: IO (Int64)
{-# LINE 297 "System/Posix/Files/Common.hsc" #-}
    let frac = toInteger nsec % 10^(9::Int)

{-# LINE 310 "System/Posix/Files/Common.hsc" #-}
    return $ fromRational $ toRational sec + frat

I'm now stuck trying to figure out what to look at next in tracking this problem down. Can you help?

Problem with fdatasync when cross compiling to aarch64 on Mac OS X

The error output is:

"inplace/bin/ghc-stage1" -hisuf hi -osuf  o -hcsuf hc -static  -H64m -O0    -this-package-key unix_6KxsoniXeYR9o99eChzwLX -hide-all-packages -i -ilibraries/unix/. -ilibraries/unix/dist-install/build -ilibraries/unix/dist-install/build/autogen -Ilibraries/unix/dist-install/build -Ilibraries/unix/dist-install/build/autogen -Ilibraries/unix/include    -optP-include -optPlibraries/unix/dist-install/build/autogen/cabal_macros.h -package-key base_62ctz6fVRDGAMD7GZKNkAJ -package-key bytes_BBgXs4iMVG62xkLTXxSQ78 -package-key time_Ca2vuoP20B2BBf1t5jg5Kb -Wall -XHaskell2010 -O -fllvm  -no-user-package-db -rtsopts      -odir libraries/unix/dist-install/build -hidir libraries/unix/dist-install/build -stubdir libraries/unix/dist-install/build   -c libraries/unix/dist-install/build/System/Posix/Unistd.hs -o libraries/unix/dist-install/build/System/Posix/Unistd.o

/var/folders/pv/pfxcyy117v31vt6lsshtgr_w0000gn/T/ghc3154_0/ghc3154_2.c:9:110:
     error: implicit declaration of function 'fdatasync' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
HsInt32 ghczuwrapperZC0ZCunixzu6KxsoniXeYR9o99eChzzwLXZCSystemziPosixziUnistdZCfdatasync(HsInt32 a1) {return fdatasync(a1);}

The bug is introduced in commit 98eced8.

The compiler I was using was LLVM 3.6's clang in a wrapper script called aarch64-apple-darwin14-clang. The contents of this file are:

#!/bin/sh
TARGET_PLATFORM=`xcrun --show-sdk-path --sdk iphoneos`
TARGET_GCC=/usr/local/clang+llvm-3.6.0-rc2-x86_64-apple-darwin/bin/clang
TARGET_CFLAGS="-isysroot $TARGET_PLATFORM -arch arm64 -miphoneos-version-min=7.0"

exec $TARGET_GCC $TARGET_CFLAGS "$@"

The problem is simply that you cannot use AC_CHECK_FUNCS in configure.ac to
check for the existence of a library function when cross-compiling.

This is detailed here

My work-around to the issue is to run configure manually and then edit include/HsUnixConfig.h
manually and set:

 #define HAVE_FDATASYNC 0

setFileTimesHiRes apparently can receive EINTR

man utimensat doesn't document it (at least on Ubuntu 16.04 -- but this page seems to do for futimens), but it seems that utimensat() can return errno = EINTR when interrupted.

This just occurred to me when sending SIGSTOP (Ctrl-Z) to my program and then resuming:

setFileTimesHiRes: interrupted (Interrupted system call)

If it can really return EINTR, we'd have to change

setFileTimesHiRes name atime mtime =
  withFilePath name $ \s ->
    withArray [toCTimeSpec atime, toCTimeSpec mtime] $ \times ->
      throwErrnoPathIfMinus1_ "setFileTimesHiRes" name $
        c_utimensat (-100) s times 0

to use throwErrnoIfMinus1Retry_ instead.

getDirectoryContents:readDirStream: invalid argument (Invalid argument)

I've spotted a transient error on macOS travis-ci job:

Jun 05 09:20:40 .stack-work/dist/x86_64-osx-nix/Cabal-1.24.2.0/build/.stack-work/dist/x86_64-osx-nix/Cabal-1.24.2.0/build/autogen:
Jun 05 09:20:40 getDirectoryContents:readDirStream: invalid argument (Invalid argument)
Jun 05 09:20:46 Completed 107 action(s).

Workaround is to restart the CI job, but I wonder what goes wrong?

Source:

readDirStream :: DirStream -> IO FilePath

Missing O_NOFOLLOW

This is really annoying. I don't even understand why this library attempts to pre-select which flags I can pass in or not. That's not how a low-level library should be designed.

Since this library is about POSIX stuff, you should simply allow all POSIX flags, see http://www.unix.com/man-page/posix/3p/open/

O_NOFOLLOW If path names a symbolic link, fail and set errno to [ELOOP].

configure sets seekdir/telldir to yes for android cross compilation.

Using gnu gold as a linker, specifically:
GNU gold (binutils-2.25-0666073 2.25.51.20141117) 1.11

compiling and linking:

/* Define seekdir to an innocuous variant, in case <limits.h> declares seekdir.
   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
#define seekdir innocuous_seekdir

/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char seekdir (); below.
    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    <limits.h> exists even on freestanding compilers.  */

#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif

#undef seekdir

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
#ifdef __cplusplus
extern "C"
#endif
char seekdir ();
/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined __stub_seekdir || defined __stub___seekdir
choke me
#endif

int
main ()
{
return seekdir ();
  ;
  return 0;
}

does not result in an error, even though seekdir is not resolved:

$ nm -u a.out
         U __cxa_atexit
         U __libc_init
         U seekdir

this then later results in seekdir missing when trying to deploy the code.

I was not able to convince gold to complain about the unresolved seekdir.

compilation error: sys/mman.h: No such file or directory

Did not found mman.h on x86-64 (Ubuntu GNOME) because the sys folder doesn't exist.
I replaced sys with linux and everything is working now:

libc6-dev-i386: /usr/include/sys/mman.h

linux-libc-dev: /usr/include/linux/mman.h

Add `System.Posix.MessageQueue`.

The message queue API is curiously missing from the unix package. Is there a reason for it other than "nobody's cared enough to implement it yet"?

Does not typecheck with time-1.8 (HEAD)

libraries/unix/System/Posix/Files/Common.hsc:356:14: error:
    • No instance for (Fractional POSIXTime)
        arising from a use of ‘fromRational’
    • In the second argument of ‘($)’, namely
        ‘fromRational $ toRational sec + frac’
      In a stmt of a 'do' block:
        return $ fromRational $ toRational sec + frac
      In the expression:
        do sec <- ((\ hsc_ptr -> peekByteOff hsc_ptr 104)) stat_ptr ::
                    IO EpochTime
           nsec <- ((\ hsc_ptr -> peekByteOff hsc_ptr 112)) stat_ptr ::
                     IO (Int64)
           let frac = toInteger nsec % 10 ^ (9 :: Int)
           return $ fromRational $ toRational sec + frac

libraries/unix/System/Posix/Files/Common.hsc:419:38: error:
    • No instance for (Real POSIXTime)
        arising from a use of ‘toRational’
    • In the second argument of ‘($)’, namely ‘toRational t’
      In the expression: properFraction $ toRational t
      In a pattern binding: (sec', frac') = properFraction $ toRational t

libraries/unix/System/Posix/Files/Common.hsc:449:38: error:
    • No instance for (Real POSIXTime)
        arising from a use of ‘toRational’
    • In the second argument of ‘($)’, namely ‘toRational t’
      In the expression: properFraction $ toRational t
      In a pattern binding: (sec', frac') = properFraction $ toRational t

Strange-ness with SIGINFO and SIGWINCH

When working on building an x86_64-linux to aarch64-linux cross compiler, I got the error:

libraries/unix/System/Posix/Signals/Exts.hsc:52:1:
    Unacceptable result type in foreign declaration:
      Safe Haskell is on, all FFI imports must be in the IO monad
    When checking declaration:
      foreign import ccall unsafe "static __hsunix_SIGWINCH" sigWINCH :: CInt

which I do not get when building a native compiler. The problems here are as follows:

SIGWINCH not defined

The above foreign import statement is enclosed in an #ifdef like this:

# ifdef SIGWINCH
foreign import ccall unsafe "__hsunix_SIGWINCH"   sigWINCH   :: CInt
# endif

but the SIGWINCH identifier is never defined, because no-one ever added it to the list os signals to look for in configure.ac (the same is true for SIGINFO).

CPP not working correctly during cross-compiling

However, with SIGWINCH undefined, the parser should have dropped that line completely. Since there is no warning on native compiles, this suggests the CPP is not working correctly during cross compiling. Obviously not a problem to be fixed in the unix package, but a contributor to even finding the other problems here.

The #ifdef is not correct.

The current configure script, when it finds a signal SIGXXXX defines CONST_SIGXXXX so the #ifdef should be using that instead of the bare signal name.

Detecting SIGINFO not working correctly.

If I update configure.ac to detect these two signals (on Linux), I get the following in the file include/HsUnixConfig.h:

#define CONST_SIGINFO -1
#define CONST_SIGWINCH 28

The value for SIGWINCH is fine, but the value for SIGINFO is not. It turns out that SIGINFO is a BSD-ism that is not available on Linux. The configure.ac detection code needs to be fixed to leave CONST_SIGINFO undefined on platforms where SIGINFO does not exist.

Don't assume `tcdrain`/`ctermid` exists everywhere

Turns out that some platforms (e.g. versions prior to API level 21 of the Android API, as reported via #54, as can be seen from https://github.com/android/platform_bionic/blob/master/libc/include/termios.h + https://github.com/android/platform_bionic/blob/master/libc/include/android/legacy_termios_inlines.h) are lacking at least the POSIX.1-2001 termios(3) functions

  • tcdrain(3) and
  • ctermid(3)

However, unix currently assumes those are available unconditionally

incompatible pointer type compile warnings for `getgrnam_r` et al.

Filing this ticket so it doesn't get forgotten... hopefully...

[24 of 38] Compiling System.Posix.User ( dist/build/System/Posix/User.hs, dist/build/System/Posix/User.o )
/tmp/ghc32048_0/ghc32048_139.c: In function ‘ghczuwrapperZC0ZCunixzm2zi7zi0zi2ZCSystemziPosixziUserZCgetgrnamzur’:

/tmp/ghc32048_0/ghc32048_139.c:8:166:
     warning: passing argument 5 of ‘getgrnam_r’ from incompatible pointer type
     HsInt32 ghczuwrapperZC0ZCunixzm2zi7zi0zi2ZCSystemziPosixziUserZCgetgrnamzur(void* a1, void* a2, void* a3, HsWord64 a4, void** a5) {return getgrnam_r(a1, a2, a3, a4, a5);}
                                                                                                                                                                          ^

In file included from include/HsUnix.h:72:0:
    0,
                     from /tmp/ghc32048_0/ghc32048_139.c:7:

/usr/include/grp.h:152:12:
     note: expected ‘struct group ** __restrict__’ but argument is of type ‘void **’
     extern int getgrnam_r (const char *__restrict __name,
                ^
/tmp/ghc32048_0/ghc32048_139.c: In function ‘ghczuwrapperZC1ZCunixzm2zi7zi0zi2ZCSystemziPosixziUserZCgetgrgidzur’:

/tmp/ghc32048_0/ghc32048_139.c:10:169:
     warning: passing argument 5 of ‘getgrgid_r’ from incompatible pointer type
     HsInt32 ghczuwrapperZC1ZCunixzm2zi7zi0zi2ZCSystemziPosixziUserZCgetgrgidzur(HsWord32 a1, void* a2, void* a3, HsWord64 a4, void** a5) {return getgrgid_r(a1, a2, a3, a4, a5);}
                                                                                                                                                                             ^

In file included from include/HsUnix.h:72:0:
    0,
                     from /tmp/ghc32048_0/ghc32048_139.c:7:

/usr/include/grp.h:144:12:
     note: expected ‘struct group ** __restrict__’ but argument is of type ‘void **’
     extern int getgrgid_r (__gid_t __gid, struct group *__restrict __resultbuf,
                ^
/tmp/ghc32048_0/ghc32048_145.c: In function ‘ghczuwrapperZC0ZCunixzm2zi7zi0zi2ZCSystemziPosixziUserZCgetgrnamzur’:

/tmp/ghc32048_0/ghc32048_145.c:8:166:
     warning: passing argument 5 of ‘getgrnam_r’ from incompatible pointer type
     HsInt32 ghczuwrapperZC0ZCunixzm2zi7zi0zi2ZCSystemziPosixziUserZCgetgrnamzur(void* a1, void* a2, void* a3, HsWord64 a4, void** a5) {return getgrnam_r(a1, a2, a3, a4, a5);}
                                                                                                                                                                          ^

In file included from include/HsUnix.h:72:0:
    0,
                     from /tmp/ghc32048_0/ghc32048_145.c:7:

/usr/include/grp.h:152:12:
     note: expected ‘struct group ** __restrict__’ but argument is of type ‘void **’
     extern int getgrnam_r (const char *__restrict __name,
                ^
/tmp/ghc32048_0/ghc32048_145.c: In function ‘ghczuwrapperZC1ZCunixzm2zi7zi0zi2ZCSystemziPosixziUserZCgetgrgidzur’:

/tmp/ghc32048_0/ghc32048_145.c:10:169:
     warning: passing argument 5 of ‘getgrgid_r’ from incompatible pointer type
     HsInt32 ghczuwrapperZC1ZCunixzm2zi7zi0zi2ZCSystemziPosixziUserZCgetgrgidzur(HsWord32 a1, void* a2, void* a3, HsWord64 a4, void** a5) {return getgrgid_r(a1, a2, a3, a4, a5);}
                                                                                                                                                                             ^

In file included from include/HsUnix.h:72:0:
    0,
                     from /tmp/ghc32048_0/ghc32048_145.c:7:

/usr/include/grp.h:144:12:
     note: expected ‘struct group ** __restrict__’ but argument is of type ‘void **’
     extern int getgrgid_r (__gid_t __gid, struct group *__restrict __resultbuf,
                ^

forkProcess fails with +RTS -N

I have a program in which I use forkProcess. When it is run with -threaded +RTS -N1, it works fine, but when I use -threaded +RTS -N2 I get this error:

failed to create OS thread: Resource temporarily unavailable

I haven't been able to reproduce this issue in a small test case, only within the larger program. To provide some context though, it' called only from the following function:

pOpen :: FilePath -> [String] -> (Handle -> IO a) -> IO a
pOpen fp args func = do
  pipepair <- createPipe
  pid <- do
    p <- Control.Exception.try (forkProcess $ childstuff pipepair)
    case p of
      Right x -> return x
      Left (e :: Control.Exception.IOException) -> fail ("Error in fork: " ++ show e)
  retval <- callfunc pipepair
  let rv = seq retval retval
  void $ getProcessStatus True False pid
  return rv
  where
    callfunc pipepair = do
      closeFd (fst pipepair)
      h <- fdToHandle (snd pipepair)
      x <- func h
      hClose h
      return $! x

    childstuff pipepair = do
              void $ dupTo (fst pipepair) stdInput
              closeFd $ fst pipepair
              closeFd $ snd pipepair
              executeFile fp True args Nothing

GHC Version: 7.10.3
unix version: 2.7.1.0
OS: Ubuntu 16.04

Use of empty FilePath to indicate end of DirStream seems deeply questionable

For example:

readDirStream :: DirStream -> IO RawFilePath
readDirStream (DirStream dirp) =
  alloca $ \ptr_dEnt  -> loop ptr_dEnt
 where
  loop ptr_dEnt = do
    resetErrno
    r <- c_readdir dirp ptr_dEnt
    if (r == 0)
         then do dEnt <- peek ptr_dEnt
                 if (dEnt == nullPtr)
                    then return BC.empty
                    else do
                     entry <- (d_name dEnt >>= peekFilePath)
                     c_freeDirEnt dEnt
                     return entry
         else do errno <- getErrno
                 if (errno == eINTR) then loop ptr_dEnt else do
                 let (Errno eo) = errno
                 if (eo == 0)
                    then return BC.empty
                    else throwErrno "readDirStream"

Wouldn't it be far better if we returned 'Maybe RawFilePath'? Ditto for FilePath API.

Don't assume WCOREDUMP exists

quoting the man-page:

WCOREDUMP(status)
returns true if the child produced a core dump. This macro should be employed only if WIFSIGNALED returned true. This macro is not specified in POSIX.1-2001 and is not available on some UNIX implementations (e.g., AIX, SunOS). Only use this enclosed in #ifdef WCOREDUMP ... #endif.

getEnvDefault: which is which?

getEnvDefault :: String -> String -> IO String

getEnvDefault is a wrapper around getEnv where the programmer can specify a fallback if the variable is not found in the environment.”

Well, thanks Obama, but what is the variable name and what is the fallback?

"exclusive = True" may lead to undefined behavior

It's not very well documented, because O_CREAT is not passed like the other flags via OpenFileFlags, but implicitly via Maybe FileMode.

The manpage says that

If O_EXCL is set and O_CREAT is not set, the result is undefined.

This library should either make the correspondence of those input arguments clear or make it impossible to use the combination. The following would already be quite an improvement:

-- |Correspond to some of the int flags from C's fcntl.h.
data OpenFileFlags =
 OpenFileFlags {
    append    :: Bool,           -- ^ O_APPEND
    exclusive :: Bool,           -- ^ O_EXCL, result is undefined if O_CREAT is False
    noctty    :: Bool,           -- ^ O_NOCTTY
    nonBlock  :: Bool,           -- ^ O_NONBLOCK
    trunc     :: Bool,           -- ^ O_TRUNC
    creat     :: Maybe FileMode  -- ^ O_CREAT 
 }

And then remove the extraneous Maybe FileMode arguments from open_.

String and ByteString implementations have desynchronized

I've been Backpack'ifying unix on the suggestion of @hvr, and I have realized that the String and ByteString implementations have desynchronized in a few cases. I'm still working my way through the modules but here are the ones I've noticed:

System.Posix.Env

  • ByteString does not implement/export setEnvironment
  • ByteString: unsetEnv name = putEnv (name ++ "=") Pretty sure this is a type error
  • ByteString: putEnv uses useAsCString to allocate the string passed to putenv, but String has a comment indicating we must not free the string after putenv according to SUSv2

Actually, amazingly enough, I checked the rest of the implementations and this was the only desynchronization.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.