Skip to content

Commit 7036906

Browse files
hasufellmatil019hs-viktorbgamari
authored
Backports for 2.7.3 (#235)
* Add regression test for #218 #218 Error was: uncaught exception: IOException of type InvalidArgument semTrywait: invalid argument (Bad file descriptor) * Fix 'semTrywait: invalid argument (Bad file descriptor)' wrt #218 * Add regression test for putEnv wrt #68 * Synchronize ByteString and String modules And fix free-bug in 'putEnv'. Fixes #68 * Add cabal.project * Fix the error handling of posix_fallocate other than FreeBSD This commit introduces a CPP guard to take care of the difference between OSes of the errors of posix_fallocate. On Linux and NetBSD, posix_fallocate reports error by returning an error number. errno is not set. On the other hand, on FreeBSD, posix_fallocate returns -1 and sets errno. The existing code could handle FreeBSD-style errors only. * Remove obsolete FreeBSD-style error handling The FreeBSD-style error (return -1, set errno) is obsolete as of FreeBSD 11.0; it now reports errors as same as the other OSes. * Future-proof glibc version check * Resource: Fix warning in case of no RLIM_SAVED_{CUR,MAX} This previously failed to build with a warning on FreeBSD 11.2 * Bump to 2.7.3 * Add Eq and Show instance to BaudRate Needed for test suite * Add CI * Tighten lower base bound to only allow GHC-8.2+ Co-authored-by: matil019 <[email protected]> Co-authored-by: Viktor Dukhovni <[email protected]> Co-authored-by: Ben Gamari <[email protected]>
1 parent 184c454 commit 7036906

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+920
-637
lines changed

.github/workflows/ci.yml

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
name: ci
2+
on:
3+
- push
4+
- pull_request
5+
6+
defaults:
7+
run:
8+
shell: bash
9+
10+
jobs:
11+
build:
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: true
15+
matrix:
16+
os: [ubuntu-latest, macOS-latest]
17+
ghc: ['9.2', '9.0', '8.10', '8.8', '8.6', '8.4', '8.2']
18+
steps:
19+
- uses: actions/checkout@v2
20+
- uses: haskell/actions/setup@v1
21+
id: setup-haskell-cabal
22+
with:
23+
ghc-version: ${{ matrix.ghc }}
24+
- uses: actions/cache@v2
25+
name: Cache cabal stuff
26+
with:
27+
path: |
28+
${{ steps.setup-haskell-cabal.outputs.cabal-store }}
29+
dist-newstyle
30+
key: ${{ runner.os }}-${{ matrix.ghc }}
31+
- name: Build
32+
run: |
33+
cabal --version
34+
cabal update
35+
autoreconf --version
36+
autoreconf -i
37+
cabal sdist -z -o .
38+
cabal get unix-*.tar.gz
39+
cd unix-*/
40+
cabal test all --test-show-details=direct
41+
- name: Haddock
42+
run: cabal haddock
43+
44+
centos7:
45+
runs-on: ubuntu-latest
46+
container:
47+
image: centos:7
48+
steps:
49+
- name: Install
50+
run: |
51+
yum install -y gcc gmp gmp-devel make ncurses ncurses-compat-libs xz perl autoconf
52+
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 sh
53+
- uses: actions/checkout@v2
54+
- name: Test
55+
run: |
56+
source ~/.ghcup/env
57+
cabal --version
58+
cabal update
59+
autoreconf --version
60+
autoreconf -i
61+
cabal test all --test-show-details=direct
62+
63+
fedora34:
64+
runs-on: ubuntu-latest
65+
container:
66+
image: fedora:34
67+
steps:
68+
- name: Install
69+
run: |
70+
dnf install -y gcc gmp gmp-devel make ncurses ncurses-compat-libs xz perl autoconf
71+
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 sh
72+
- uses: actions/checkout@v2
73+
- name: Test
74+
run: |
75+
source ~/.ghcup/env
76+
cabal --version
77+
cabal update
78+
autoreconf --version
79+
autoreconf -i
80+
cabal test all --test-show-details=direct
81+
82+
i386:
83+
runs-on: ubuntu-latest
84+
container:
85+
image: i386/ubuntu:bionic
86+
steps:
87+
- name: Install
88+
run: |
89+
apt-get update -y
90+
apt-get install -y autoconf build-essential zlib1g-dev libgmp-dev curl
91+
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 sh
92+
- uses: actions/checkout@v1
93+
- name: Test
94+
run: |
95+
source ~/.ghcup/env
96+
cabal --version
97+
cabal update
98+
autoreconf --version
99+
autoreconf -i
100+
cabal v2-test --constraint 'optparse-applicative -process' --constraint 'QuickCheck +old-random' --constraint 'tasty -unix' all
101+
102+
arm:
103+
runs-on: ubuntu-latest
104+
strategy:
105+
fail-fast: false
106+
matrix:
107+
arch: ['armv7', 'aarch64']
108+
steps:
109+
- uses: actions/checkout@v2
110+
- uses: uraimo/[email protected]
111+
timeout-minutes: 120
112+
with:
113+
arch: ${{ matrix.arch }}
114+
distro: ubuntu20.04
115+
githubToken: ${{ github.token }}
116+
install: |
117+
apt-get update -y
118+
apt-get install -y ghc cabal-install autoconf
119+
run: |
120+
cabal --version
121+
cabal update
122+
autoreconf --version
123+
autoreconf -i
124+
cabal v2-test --constraint 'optparse-applicative -process' --constraint 'QuickCheck +old-random' --constraint 'tasty -unix' all

System/Posix/Env/ByteString.hsc

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
{-# LANGUAGE CApiFFI #-}
22
{-# LANGUAGE Trustworthy #-}
3-
#if __GLASGOW_HASKELL__ >= 709
4-
{-# OPTIONS_GHC -fno-warn-trustworthy-safe #-}
5-
#endif
63

74
-----------------------------------------------------------------------------
85
-- |
@@ -24,24 +21,28 @@ module System.Posix.Env.ByteString (
2421
, getEnvDefault
2522
, getEnvironmentPrim
2623
, getEnvironment
24+
, setEnvironment
2725
, putEnv
2826
, setEnv
29-
, unsetEnv
27+
, unsetEnv
28+
, clearEnv
3029

3130
-- * Program arguments
3231
, getArgs
3332
) where
3433

3534
#include "HsUnix.h"
3635

36+
import Control.Monad
3737
import Foreign
3838
import Foreign.C
39-
import Control.Monad ( liftM )
4039
import Data.Maybe ( fromMaybe )
4140

41+
import System.Posix.Env ( clearEnv )
4242
import qualified Data.ByteString as B
4343
import qualified Data.ByteString.Char8 as BC
4444
import Data.ByteString (ByteString)
45+
import Data.ByteString.Internal (ByteString (PS), memcpy)
4546

4647
-- |'getEnv' looks up a variable in the environment.
4748

@@ -55,8 +56,8 @@ getEnv name = do
5556
else return Nothing
5657

5758
-- |'getEnvDefault' is a wrapper around 'getEnv' where the
58-
-- programmer can specify a fallback if the variable is not found
59-
-- in the environment.
59+
-- programmer can specify a fallback as the second argument, which will be
60+
-- used if the variable is not found in the environment.
6061

6162
getEnvDefault ::
6263
ByteString {- ^ variable name -} ->
@@ -100,6 +101,18 @@ getEnvironment = do
100101
| BC.head y == '=' = (x,B.tail y)
101102
| otherwise = error $ "getEnvironment: insane variable " ++ BC.unpack x
102103

104+
-- |'setEnvironment' resets the entire environment to the given list of
105+
-- @(key,value)@ pairs.
106+
--
107+
-- @since 2.7.3
108+
setEnvironment ::
109+
[(ByteString,ByteString)] {- ^ @[(key,value)]@ -} ->
110+
IO ()
111+
setEnvironment env = do
112+
clearEnv
113+
forM_ env $ \(key,value) ->
114+
setEnv key value True {-overwrite-}
115+
103116
-- |The 'unsetEnv' function deletes all instances of the variable name
104117
-- from the environment.
105118

@@ -120,15 +133,25 @@ foreign import capi unsafe "HsUnix.h unsetenv"
120133
c_unsetenv :: CString -> IO ()
121134
# endif
122135
#else
123-
unsetEnv name = putEnv (name ++ "=")
136+
unsetEnv name = putEnv (BC.snoc name '=')
124137
#endif
125138

126139
-- |'putEnv' function takes an argument of the form @name=value@
127140
-- and is equivalent to @setEnv(key,value,True{-overwrite-})@.
128141

129142
putEnv :: ByteString {- ^ "key=value" -} -> IO ()
130-
putEnv keyvalue = B.useAsCString keyvalue $ \s ->
131-
throwErrnoIfMinus1_ "putenv" (c_putenv s)
143+
putEnv (PS fp o l) = withForeignPtr fp $ \p -> do
144+
-- https://pubs.opengroup.org/onlinepubs/009696899/functions/putenv.html
145+
--
146+
-- "the string pointed to by string shall become part of the environment,
147+
-- so altering the string shall change the environment. The space used by
148+
-- string is no longer used once a new string which defines name is passed to putenv()."
149+
--
150+
-- hence we must not free the buffer
151+
buf <- mallocBytes (l+1)
152+
memcpy buf (p `plusPtr` o) l
153+
pokeByteOff buf l (0::Word8)
154+
throwErrnoIfMinus1_ "putenv" (c_putenv (castPtr buf))
132155

133156
foreign import ccall unsafe "putenv"
134157
c_putenv :: CString -> IO CInt

System/Posix/Fcntl.hsc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ fileAdvise _ _ _ _ = return ()
9292
fileAllocate :: Fd -> FileOffset -> FileOffset -> IO ()
9393
#if HAVE_POSIX_FALLOCATE
9494
fileAllocate fd off len = do
95-
throwErrnoIfMinus1_ "fileAllocate" (c_posix_fallocate (fromIntegral fd) (fromIntegral off) (fromIntegral len))
95+
ret <- c_posix_fallocate (fromIntegral fd) (fromIntegral off) (fromIntegral len)
96+
if ret == 0
97+
then pure ()
98+
else ioError (errnoToIOError "fileAllocate" (Errno ret) Nothing Nothing)
9699

97100
foreign import capi safe "fcntl.h posix_fallocate"
98101
c_posix_fallocate :: CInt -> COff -> COff -> IO CInt

System/Posix/Resource.hsc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,18 @@ unpackRLimit other
111111

112112
packRLimit :: ResourceLimit -> Bool -> CRLim
113113
packRLimit ResourceLimitInfinity _ = (#const RLIM_INFINITY)
114-
#ifdef RLIM_SAVED_CUR
114+
#if defined(RLIM_SAVED_CUR)
115115
packRLimit ResourceLimitUnknown True = (#const RLIM_SAVED_CUR)
116116
#endif
117-
#ifdef RLIM_SAVED_MAX
117+
#if defined(RLIM_SAVED_MAX)
118118
packRLimit ResourceLimitUnknown False = (#const RLIM_SAVED_MAX)
119119
#endif
120+
#if ! defined(RLIM_SAVED_MAX) && !defined(RLIM_SAVED_CUR)
121+
packRLimit ResourceLimitUnknown _ =
122+
error
123+
$ "System.Posix.Resource.packRLimit: " ++
124+
"ResourceLimitUnknown but RLIM_SAVED_MAX/RLIM_SAVED_CUR not defined by platform"
125+
#endif
120126
packRLimit (ResourceLimit other) _ = fromIntegral other
121127

122128

System/Posix/Semaphore.hsc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#else
44
{-# LANGUAGE Trustworthy #-}
55
#endif
6+
{-# LANGUAGE CApiFFI #-}
67
-----------------------------------------------------------------------------
78
-- |
89
-- Module : System.Posix.Semaphore
@@ -114,18 +115,18 @@ semGetValue_ sem ptr = do throwErrnoIfMinus1Retry_ "semGetValue" $
114115
cint <- peek ptr
115116
return $ fromEnum cint
116117

117-
foreign import ccall safe "sem_open"
118+
foreign import capi safe "semaphore.h sem_open"
118119
sem_open :: CString -> CInt -> CMode -> CUInt -> IO (Ptr ())
119-
foreign import ccall safe "sem_close"
120+
foreign import capi safe "semaphore.h sem_close"
120121
sem_close :: Ptr () -> IO CInt
121-
foreign import ccall safe "sem_unlink"
122+
foreign import capi safe "semaphore.h sem_unlink"
122123
sem_unlink :: CString -> IO CInt
123124

124-
foreign import ccall safe "sem_wait"
125+
foreign import capi safe "semaphore.h sem_wait"
125126
sem_wait :: Ptr () -> IO CInt
126-
foreign import ccall safe "sem_trywait"
127+
foreign import capi safe "semaphore.h sem_trywait"
127128
sem_trywait :: Ptr () -> IO CInt
128-
foreign import ccall safe "sem_post"
129+
foreign import capi safe "semaphore.h sem_post"
129130
sem_post :: Ptr () -> IO CInt
130-
foreign import ccall safe "sem_getvalue"
131+
foreign import capi safe "semaphore.h sem_getvalue"
131132
sem_getvalue :: Ptr () -> Ptr CInt -> IO Int

System/Posix/Terminal/Common.hsc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ data BaudRate
335335
| B38400
336336
| B57600
337337
| B115200
338+
deriving (Eq, Show)
338339

339340
inputSpeed :: TerminalAttributes -> BaudRate
340341
inputSpeed termios = unsafePerformIO $ do

cabal.project

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
packages: .
2+
3+
tests: True
4+
5+
constraints:
6+
tasty -unix, optparse-applicative -process

cbits/HsUnix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ int __hsunix_push_module(int fd, const char *module)
4747
* re-entrant.
4848
*/
4949

50-
#if defined (__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 23)
50+
#if defined (__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 23))
5151
#define USE_READDIR_R 0
5252
#else
5353
#define USE_READDIR_R 1

changelog.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Changelog for [`unix` package](http://hackage.haskell.org/package/unix)
22

3+
## 2.7.2.3 *Unreleased*
4+
5+
* Resource: Fix warning in case of no RLIM_SAVED_{CUR,MAX}
6+
7+
* Future-proof glibc version check
8+
9+
* Fix the error handling of posix_fallocate in non-FreeBSD
10+
11+
* Synchronize ByteString and String modules and fix grave bug in 'putEnv'
12+
13+
* Fix 'semTrywait: invalid argument (Bad file descriptor)' wrt #218
14+
15+
* Improve error messages
16+
17+
* Improve tests
18+
19+
* Don't show repo as modified after configure
20+
321
## 2.7.2.2 *May 2017*
422

523
* Bundled with GHC 8.2.1

tests/fdReadBuf001.hs renamed to tests/FdReadBuf001.hs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1-
{-# LANGUAGE NoMonomorphismRestriction #-}
1+
module Main where
2+
23
import System.Posix
34
import Control.Monad
4-
import Foreign
5+
import Foreign hiding (void)
56
import Control.Concurrent
67
import Data.Char
78
import System.Exit
89

9-
size = 10000
10-
block = 512
11-
10+
main :: IO ()
1211
main = do
12+
let size = 10000
13+
block = 512
1314
(rd,wr) <- createPipe
1415
let bytes = take size (map (fromIntegral.ord) (cycle ['a'..'z']))
15-
allocaBytes size $ \p -> do
16-
pokeArray p bytes
17-
forkIO $ do r <- fdWriteBuf wr p (fromIntegral size)
18-
when (fromIntegral r /= size) $ error "fdWriteBuf failed"
16+
void $ forkIO $ allocaBytes size $ \p -> do
17+
pokeArray p bytes
18+
r <- fdWriteBuf wr p (fromIntegral size)
19+
when (fromIntegral r /= size) $ error "fdWriteBuf failed"
1920
allocaBytes block $ \p -> do
2021
let loop text = do
21-
r <- fdReadBuf rd p block
22+
r <- fdReadBuf rd p (fromIntegral block)
2223
let (chunk,rest) = splitAt (fromIntegral r) text
2324
chars <- peekArray (fromIntegral r) p
2425
when (chars /= chunk) $ error $ "mismatch: expected="++show chunk++", found="++show chars

0 commit comments

Comments
 (0)