Commits

Bryan O'Sullivan committed f15e9f5

Block signals properly for a pile more API entry points

How'd I miss these???

  • Participants
  • Parent commits e4550b3
  • Tags 0.1.1.2

Comments (0)

Files changed (4)

Database/MySQL/Base.hs

     , resFetchFields :: Ptr MYSQL_RES -> IO (Ptr Field)
     , resFetchRow :: Ptr MYSQL_RES -> IO MYSQL_ROW
     , resFetchLengths :: Ptr MYSQL_RES -> IO (Ptr CULong)
+    , resFreeResult :: Ptr MYSQL_RES -> IO ()
     } | EmptyResult
 
 -- | A row cursor, used by 'rowSeek' and 'rowTell'.
               mysql_fetch_fields_nonblock
               mysql_fetch_row_nonblock
               mysql_fetch_lengths_nonblock
+              mysql_free_result_nonblock
 
 -- | Initiate a row-by-row retrieval of a result.
 --
             mysql_fetch_fields
             mysql_fetch_row
             mysql_fetch_lengths
+            mysql_free_result
 
 frobResult :: String
            -> (Ptr MYSQL -> IO (Ptr MYSQL_RES))
            -> (Ptr MYSQL_RES -> IO (Ptr Field))
            -> (Ptr MYSQL_RES -> IO MYSQL_ROW)
            -> (Ptr MYSQL_RES -> IO (Ptr CULong))
+           -> (Ptr MYSQL_RES -> IO ())
            -> Connection -> IO Result
-frobResult func frob fetchFieldsFunc fetchRowFunc fetchLengthsFunc conn =
+frobResult func frob fetchFieldsFunc fetchRowFunc fetchLengthsFunc
+           myFreeResult conn =
   withConn conn $ \ptr -> do
     cleanupConnResult (connResult conn)
     res <- frob ptr
            then return EmptyResult
            else connectionError func conn
       else do
-        fp <- newForeignPtr res $ freeResult_ valid res
+        fp <- newForeignPtr res $ freeResult_ valid myFreeResult res
         let ret = Result {
                     resFP = fp
                   , resFields = fromIntegral fields
                   , resFetchFields = fetchFieldsFunc
                   , resFetchRow = fetchRowFunc
                   , resFetchLengths = fetchLengthsFunc
+                  , resFreeResult = myFreeResult
                   }
-        weak <- mkWeakPtr ret (Just (freeResult_ valid res))
+        weak <- mkWeakPtr ret (Just (freeResult_ valid myFreeResult res))
         writeIORef (connResult conn) (Just weak)
         return ret
 
 -- | Immediately free the @MYSQL_RES@ value associated with this
 -- 'Result', and mark the @Result@ as invalid.
 freeResult :: Result -> IO ()
-freeResult Result{..}      = withForeignPtr resFP $ freeResult_ resValid
+freeResult Result{..}      = withForeignPtr resFP $
+                             freeResult_ resValid resFreeResult
 freeResult EmptyResult{..} = return ()
 
 -- | Check whether a 'Result' is still valid, i.e. backed by a live
 isResultValid Result{..}  = readIORef resValid
 isResultValid EmptyResult = return False
 
-freeResult_ :: IORef Bool -> Ptr MYSQL_RES -> IO ()
-freeResult_ valid ptr = do
+freeResult_ :: IORef Bool -> (Ptr MYSQL_RES -> IO ()) -> Ptr MYSQL_RES -> IO ()
+freeResult_ valid free ptr = do
   wasValid <- atomicModifyIORef valid $ \prev -> (False, prev)
-  when wasValid $ mysql_free_result ptr
+  when wasValid $ free ptr
 
 fetchRow :: Result -> IO [Maybe ByteString]
 fetchRow res@Result{..}  = withRes "fetchRow" res $ \ptr -> do

Database/MySQL/Base/C.hsc

     , mysql_fetch_row_nonblock
     -- * Working with results
     , mysql_free_result
+    , mysql_free_result_nonblock
     , mysql_fetch_fields
     , mysql_fetch_fields_nonblock
     , mysql_data_seek
     -> CString                  -- ^ Ciphers.
     -> IO MyBool
 
-foreign import ccall unsafe mysql_close
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_close" mysql_close
     :: Ptr MYSQL -> IO ()
 
-foreign import ccall unsafe mysql_ping
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_ping" mysql_ping
     :: Ptr MYSQL -> IO CInt
 
 foreign import ccall safe mysql_thread_id
     :: Ptr MYSQL -> IO CULong
 
-foreign import ccall unsafe mysql_autocommit
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_autocommit" mysql_autocommit
     :: Ptr MYSQL -> MyBool -> IO MyBool
 
-foreign import ccall unsafe mysql_change_user
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_change_user" mysql_change_user
     :: Ptr MYSQL
     -> CString                  -- ^ user
     -> CString                  -- ^ password
     -> CString                  -- ^ database
     -> IO MyBool
 
-foreign import ccall unsafe mysql_select_db
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_select_db" mysql_select_db
     :: Ptr MYSQL
     -> CString
     -> IO CInt
 foreign import ccall safe mysql_get_ssl_cipher
     :: Ptr MYSQL -> IO CString
 
-foreign import ccall unsafe mysql_stat
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_stat" mysql_stat
     :: Ptr MYSQL -> IO CString
 
 foreign import ccall unsafe "mysql_signals.h _hs_mysql_real_query" mysql_real_query
 foreign import ccall safe mysql_affected_rows
     :: Ptr MYSQL -> IO CULLong
 
-foreign import ccall unsafe mysql_store_result
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_store_result" mysql_store_result
     :: Ptr MYSQL -> IO (Ptr MYSQL_RES)
 
-foreign import ccall unsafe mysql_use_result
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_use_result"  mysql_use_result
     :: Ptr MYSQL -> IO (Ptr MYSQL_RES)
 
-foreign import ccall unsafe mysql_free_result
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_free_result" mysql_free_result
     :: Ptr MYSQL_RES -> IO ()
 
-foreign import ccall unsafe mysql_fetch_fields
+foreign import ccall safe "mysql.h mysql_free_result" mysql_free_result_nonblock
+    :: Ptr MYSQL_RES -> IO ()
+
+foreign import ccall safe mysql_fetch_fields
     :: Ptr MYSQL_RES -> IO (Ptr Field)
 
 foreign import ccall safe "mysql.h mysql_fetch_fields" mysql_fetch_fields_nonblock
 foreign import ccall safe mysql_row_tell
     :: Ptr MYSQL_RES -> IO MYSQL_ROW_OFFSET
 
-foreign import ccall unsafe mysql_next_result
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_next_result" mysql_next_result
     :: Ptr MYSQL -> IO CInt
 
-foreign import ccall unsafe mysql_commit
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_commit" mysql_commit
     :: Ptr MYSQL -> IO MyBool
 
-foreign import ccall unsafe mysql_rollback
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_rollback" mysql_rollback
     :: Ptr MYSQL -> IO MyBool
 
-foreign import ccall unsafe mysql_fetch_row
+foreign import ccall unsafe "mysql_signals.h _hs_mysql_fetch_row" mysql_fetch_row
     :: Ptr MYSQL_RES -> IO MYSQL_ROW
 
 foreign import ccall safe "mysql.h mysql_fetch_row" mysql_fetch_row_nonblock
     :: Ptr MYSQL_RES -> IO MYSQL_ROW
 
-foreign import ccall unsafe mysql_fetch_lengths
+foreign import ccall safe mysql_fetch_lengths
     :: Ptr MYSQL_RES -> IO (Ptr CULong)
 
 foreign import ccall safe "mysql.h mysql_fetch_lengths" mysql_fetch_lengths_nonblock

cbits/mysql_signals.c

     return ret;
 }
 
+my_bool STDCALL _hs_mysql_commit(MYSQL * mysql)
+{
+    my_bool ret;
+    block_rts_signals();
+    ret = mysql_commit(mysql);
+    unblock_rts_signals();
+    return ret;
+}
+
+my_bool STDCALL _hs_mysql_rollback(MYSQL * mysql)
+{
+    my_bool ret;
+    block_rts_signals();
+    ret = mysql_rollback(mysql);
+    unblock_rts_signals();
+    return ret;
+}
+
 my_bool STDCALL _hs_mysql_autocommit(MYSQL *mysql, my_bool auto_mode)
 {
     my_bool ret;
     return ret;
 }
 
+void STDCALL _hs_mysql_free_result(MYSQL_RES *result)
+{
+    block_rts_signals();
+    mysql_free_result(result);
+    unblock_rts_signals();
+}
+
 int STDCALL _hs_mysql_next_result(MYSQL *mysql)
 {
     int ret;

include/mysql_signals.h

 int STDCALL _hs_mysql_real_query(MYSQL *mysql, const char *q,
 				 unsigned long length);
 const char *STDCALL _hs_mysql_stat(MYSQL *mysql);
+my_bool STDCALL _hs_mysql_commit(MYSQL * mysql);
+my_bool STDCALL _hs_mysql_rollback(MYSQL * mysql);
 my_bool STDCALL _hs_mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
 my_bool STDCALL _hs_mysql_change_user(MYSQL *mysql, const char *user,
 				      const char *passwd, const char *db);
 unsigned long *STDCALL _hs_mysql_fetch_lengths(MYSQL_RES *result);
 MYSQL_RES *STDCALL _hs_mysql_store_result(MYSQL *mysql);
 MYSQL_RES *STDCALL _hs_mysql_use_result(MYSQL *mysql);
+void STDCALL _hs_mysql_free_result(MYSQL_RES *result);
 int STDCALL _hs_mysql_next_result(MYSQL *mysql);
+void STDCALL _hs_mysql_close(MYSQL *sock);
 
 #endif /* _mysql_signals_h */