pax_global_header00006660000000000000000000000064136461730410014517gustar00rootroot0000000000000052 comment=8ceda52afb11222558c71706769822600fc70d49 luv-1.36.0-0/000077500000000000000000000000001364617304100125515ustar00rootroot00000000000000luv-1.36.0-0/.ci/000077500000000000000000000000001364617304100132225ustar00rootroot00000000000000luv-1.36.0-0/.ci/bindcov.sh000077500000000000000000000042661364617304100152150ustar00rootroot00000000000000#!/usr/bin/env bash unbound_functions=0 skipped=() # false positives skipped+=(uv_thread_create uv_thread_create_ex) # intentionally not bound skipped+=(uv_replace_allocator) # threading/synchronization skipped+=( uv_mutex_init uv_mutex_init_recursive uv_mutex_destroy uv_mutex_lock uv_mutex_trylock uv_mutex_unlock uv_rwlock_init uv_rwlock_destroy uv_rwlock_rdlock uv_rwlock_tryrdlock uv_rwlock_rdunlock uv_rwlock_wrlock uv_rwlock_trywrlock uv_rwlock_wrunlock uv_sem_init uv_sem_destroy uv_sem_post uv_sem_wait uv_sem_trywait uv_cond_init uv_cond_destroy uv_cond_signal uv_cond_broadcast uv_barrier_init uv_barrier_destroy uv_barrier_wait uv_cond_wait uv_cond_timedwait uv_once uv_key_create uv_key_delete uv_key_get uv_key_set ) # yet to be implemented / ruled out # https://github.com/luvit/luv/issues/410 skipped+=( uv_loop_configure uv_setup_args uv_default_loop uv_loop_new uv_loop_delete uv_loop_size uv_loop_fork uv_loop_get_data uv_loop_set_data uv_strerror uv_strerror_r uv_err_name uv_err_name_r uv_handle_size uv_handle_get_type uv_handle_type_name uv_handle_get_data uv_handle_get_loop uv_handle_set_data uv_req_size uv_req_get_data uv_req_set_data uv_req_get_type uv_req_type_name uv_udp_set_source_membership uv_pipe_chmod uv_process_get_pid uv_get_osfhandle uv_open_osfhandle uv_fs_get_type uv_fs_get_result uv_fs_get_ptr uv_fs_get_path uv_fs_get_statbuf uv_ip4_addr uv_ip6_addr uv_ip4_name uv_ip6_name uv_inet_ntop uv_inet_pton uv_dlopen uv_dlclose uv_dlsym uv_dlerror ) # get all public uv_ functions from uv.h for fn in `grep -oP "UV_EXTERN [^\(]+ uv_[^\(]+\(" deps/libuv/include/uv.h | sed 's/($//' | grep -oP "[^ ]+$"`; do # skip everything in the skipped array and any initialization/cleanup fns if [[ " ${skipped[@]} " =~ " ${fn} " || $fn == *_init* || $fn == *_free* || $fn == *_cleanup ]] ; then continue fi # count all uses count=`grep -o "$fn" src/*.c | wc -l` # check if a luv_ version exists grep -Fq "l$fn" src/*.c bound=$? # not bound if [ ! $bound -eq 0 ] ; then # not used if [ $count -eq 0 ] ; then echo $fn else echo "$fn (used internally but not bound externally)" fi unbound_functions=$((unbound_functions+1)) fi done exit $unbound_functions luv-1.36.0-0/.ci/install.bat000066400000000000000000000205511364617304100153630ustar00rootroot00000000000000@echo off cd %APPVEYOR_BUILD_FOLDER% :: ========================================================= :: Set some defaults. Infer some variables. :: :: These are set globally if "%LUA_VER%" NEQ "" ( set LUA=lua set LUA_SHORTV=%LUA_VER:~0,3% ) else ( set LUA=luajit set LJ_SHORTV=%LJ_VER:~0,3% set LUA_SHORTV=5.1 ) :: defines LUA_DIR so Cmake can find this Lua install if "%LUA%"=="luajit" ( set LUA_DIR=c:\lua\%platform%\lj%LJ_SHORTV% ) else ( set LUA_DIR=c:\lua\%platform%\%LUA_VER% ) :: Now we declare a scope Setlocal EnableDelayedExpansion EnableExtensions if not defined LUAROCKS_URL set LUAROCKS_URL=https://luarocks.github.io/luarocks/releases if not defined LUAROCKS_REPO set LUAROCKS_REPO=https://luarocks.org if not defined LUA_URL set LUA_URL=http://www.lua.org/ftp if defined NOCOMPAT ( set COMPATFLAG=--nocompat ) else ( set COMPATFLAG= ) if not defined LUAJIT_GIT_REPO set LUAJIT_GIT_REPO=https://github.com/LuaJIT/LuaJIT.git if not defined LUAJIT_URL set LUAJIT_URL=https://github.com/LuaJIT/LuaJIT/archive if not defined LR_EXTERNAL set LR_EXTERNAL=c:\external if not defined LUAROCKS_INSTALL set LUAROCKS_INSTALL=%LUA_DIR%\LuaRocks :: LuaRocks <= 2.2.2 used a versioned directory :: HEAD and newer versions do not, so act accordingly. if defined LR_ROOT goto :skiplrver if "%LUAROCKS_VER%" EQU "HEAD" ( set LR_ROOT=%LUAROCKS_INSTALL% goto :skiplrver ) set LR_ROOT=%LUAROCKS_INSTALL% if %LUAROCKS_VER:~0,1% LEQ 2 ( if %LUAROCKS_VER:~2,1% LEQ 2 ( if %LUAROCKS_VER:~4,1% LEQ 3 ( set LR_ROOT=%LUAROCKS_INSTALL%\!LUAROCKS_VER:~0,3! ) ) ) :skiplrver if not defined LR_SYSTREE set LR_SYSTREE=%LUAROCKS_INSTALL%\systree if not defined SEVENZIP set SEVENZIP=7z :: :: ========================================================= :: first create some necessary directories: mkdir downloads 2>NUL :: Download and compile Lua (or LuaJIT) if "%LUA%"=="luajit" ( if not exist %LUA_DIR% ( if "%LJ_SHORTV%"=="2.1" ( :: Clone repository and checkout 2.1 branch set lj_source_folder=%APPVEYOR_BUILD_FOLDER%\downloads\luajit-%LJ_VER% if not exist !lj_source_folder! ( echo Cloning git repo %LUAJIT_GIT_REPO% !lj_source_folder! git clone %LUAJIT_GIT_REPO% !lj_source_folder! || call :die "Failed to clone repository" ) else ( cd !lj_source_folder! git pull || call :die "Failed to update repository" ) cd !lj_source_folder!\src git checkout v2.1 || call :die ) else ( set lj_source_folder=%APPVEYOR_BUILD_FOLDER%\downloads\luajit-%LJ_VER% if not exist !lj_source_folder! ( echo Downloading... %LUAJIT_URL%/v%LJ_VER%.tar.gz curl --location --silent --fail --max-time 120 --connect-timeout 30 %LUAJIT_URL%/v%LJ_VER%.tar.gz | %SEVENZIP% x -si -so -tgzip | %SEVENZIP% x -si -ttar -aoa -odownloads ) cd !lj_source_folder!\src ) :: Compiles LuaJIT if "%COMPILER%"=="MinGW" ( call mingw32-make ) else ( call msvcbuild.bat ) mkdir %LUA_DIR% 2> NUL for %%a in (bin bin\lua bin\lua\jit include lib) do ( mkdir "%LUA_DIR%\%%a" ) for %%a in (luajit.exe lua51.dll) do ( move "!lj_source_folder!\src\%%a" "%LUA_DIR%\bin" ) copy "%LUA_DIR%\bin\luajit.exe" "%LUA_DIR%\bin\lua.exe" move "!lj_source_folder!\src\lua51.lib" "%LUA_DIR%\lib" for %%a in (lauxlib.h lua.h lua.hpp luaconf.h lualib.h luajit.h) do ( copy "!lj_source_folder!\src\%%a" "%LUA_DIR%\include" ) copy "!lj_source_folder!\src\jit\*.lua" "%LUA_DIR%\bin\lua\jit" ) else ( echo LuaJIT %LJ_VER% already installed at %LUA_DIR% ) ) else ( if not exist %LUA_DIR% ( :: Download and compile Lua if not exist downloads\lua-%LUA_VER% ( curl --silent --fail --max-time 120 --connect-timeout 30 %LUA_URL%/lua-%LUA_VER%.tar.gz | %SEVENZIP% x -si -so -tgzip | %SEVENZIP% x -si -ttar -aoa -odownloads ) mkdir downloads\lua-%LUA_VER%\etc 2> NUL copy %~dp0\winmake.bat downloads\lua-%LUA_VER%\etc\winmake.bat cd downloads\lua-%LUA_VER% call etc\winmake %COMPATFLAG% call etc\winmake install %LUA_DIR% ) else ( echo Lua %LUA_VER% already installed at %LUA_DIR% ) ) if not exist %LUA_DIR%\bin\%LUA%.exe call :die "Missing Lua interpreter at %LUA_DIR%\bin\%LUA%.exe" set PATH=%LUA_DIR%\bin;%PATH% call !LUA! -v :: ========================================================== :: LuaRocks :: ========================================================== if not exist "%LR_ROOT%" ( :: Downloads and installs LuaRocks cd %APPVEYOR_BUILD_FOLDER% if %LUAROCKS_VER%==HEAD ( set lr_source_folder=%APPVEYOR_BUILD_FOLDER%\downloads\luarocks-%LUAROCKS_VER%-win32 if not exist !lr_source_folder! ( git clone https://github.com/keplerproject/luarocks.git --single-branch --depth 1 !lr_source_folder! || call :die "Failed to clone LuaRocks repository" ) else ( cd !lr_source_folder! git pull || call :die "Failed to update LuaRocks repository" ) ) else ( if not exist downloads\luarocks-%LUAROCKS_VER%-win32.zip ( echo Downloading LuaRocks... curl -L --silent --fail --max-time 120 --connect-timeout 30 --output downloads\luarocks-%LUAROCKS_VER%-win32.zip %LUAROCKS_URL%/luarocks-%LUAROCKS_VER%-win32.zip %SEVENZIP% x -aoa -odownloads downloads\luarocks-%LUAROCKS_VER%-win32.zip ) ) cd downloads\luarocks-%LUAROCKS_VER%-win32 if "%COMPILER%"=="MinGW" ( call install.bat /LUA %LUA_DIR% /Q /LV %LUA_SHORTV% /P "%LUAROCKS_INSTALL%" /TREE "%LR_SYSTREE%" /CONFIG "%LUAROCKS_INSTALL%" /MW ) else ( call install.bat /LUA %LUA_DIR% /Q /LV %LUA_SHORTV% /P "%LUAROCKS_INSTALL%" /TREE "%LR_SYSTREE%" /CONFIG "%LUAROCKS_INSTALL%" ) :: Configures LuaRocks to instruct CMake the correct generator to use. Else, CMake will pick the highest :: Visual Studio version installed if "%COMPILER%"=="MinGW" ( echo cmake_generator = "MinGW Makefiles" >> %LUAROCKS_INSTALL%\config-%LUA_SHORTV%.lua ) else ( set MSVS_GENERATORS[2008]=Visual Studio 9 2008 set MSVS_GENERATORS[2010]=Visual Studio 10 2010 set MSVS_GENERATORS[2012]=Visual Studio 11 2012 set MSVS_GENERATORS[2013]=Visual Studio 12 2013 set MSVS_GENERATORS[2015]=Visual Studio 14 2015 set MSVS_GENERATORS[2017]=Visual Studio 15 2017 set MSVS_GENERATORS[2019]=Visual Studio 16 2019 set CMAKE_GENERATOR=!MSVS_GENERATORS[%APPVEYOR_BUILD_WORKER_IMAGE:~14,4%]! :: Starting with MSVC 2019, CMake uses -A option to specify arch rather than Win64 suffix if %APPVEYOR_BUILD_WORKER_IMAGE:~14,4% leq 2017 ( if "%platform%" EQU "x64" (set CMAKE_GENERATOR=!CMAKE_GENERATOR! Win64) ) echo cmake_generator = "!CMAKE_GENERATOR!" >> %LUAROCKS_INSTALL%\config-%LUA_SHORTV%.lua ) ) if not exist "%LR_ROOT%" call :die "LuaRocks not found at %LR_ROOT%" set PATH=%LR_ROOT%;%LR_SYSTREE%\bin;%PATH% :: Lua will use just the system rocks set LUA_PATH=%LR_ROOT%\lua\?.lua;%LR_ROOT%\lua\?\init.lua set LUA_PATH=%LUA_PATH%;%LR_SYSTREE%\share\lua\%LUA_SHORTV%\?.lua set LUA_PATH=%LUA_PATH%;%LR_SYSTREE%\share\lua\%LUA_SHORTV%\?\init.lua set LUA_PATH=%LUA_PATH%;.\?.lua;.\?\init.lua set LUA_CPATH=%LR_SYSTREE%\lib\lua\%LUA_SHORTV%\?.dll;.\?.dll call luarocks --version || call :die "Error with LuaRocks installation" call luarocks list if not exist "%LR_EXTERNAL%" ( mkdir "%LR_EXTERNAL%" mkdir "%LR_EXTERNAL%\lib" mkdir "%LR_EXTERNAL%\include" ) set PATH=%LR_EXTERNAL%;%PATH% :: Exports the following variables: :: (beware of whitespace between & and ^ below) endlocal & set PATH=%PATH%&^ set LR_SYSTREE=%LR_SYSTREE%&^ set LUA_PATH=%LUA_PATH%&^ set LUA_CPATH=%LUA_CPATH%&^ set LR_EXTERNAL=%LR_EXTERNAL% echo. echo ====================================================== if "%LUA%"=="luajit" ( echo Installation of LuaJIT %LJ_VER% and LuaRocks %LUAROCKS_VER% done. ) else ( echo Installation of Lua %LUA_VER% and LuaRocks %LUAROCKS_VER% done. if defined NOCOMPAT echo Lua was built with compatibility flags disabled. ) echo Platform - %platform% echo LUA - %LUA% echo LUA_SHORTV - %LUA_SHORTV% echo LJ_SHORTV - %LJ_SHORTV% echo LUA_PATH - %LUA_PATH% echo LUA_CPATH - %LUA_CPATH% echo. echo LR_EXTERNAL - %LR_EXTERNAL% echo ====================================================== echo. goto :eof :: This blank space is intentional. If you see errors like "The system cannot find the batch label specified 'foo'" :: then try adding or removing blank lines lines above. :: Yes, really. :: http://stackoverflow.com/questions/232651/why-the-system-cannot-find-the-batch-label-specified-is-thrown-even-if-label-e :: helper functions: :: for bailing out when an error occurred :die %1 echo %1 exit /B 1 goto :eof luv-1.36.0-0/.ci/lsan_build.supp000066400000000000000000000000151364617304100162430ustar00rootroot00000000000000leak:buildvm luv-1.36.0-0/.ci/make_rockspec.sh000077500000000000000000000016461364617304100163760ustar00rootroot00000000000000#!/bin/sh version=$1 if [ -z "$version" ]; then echo "must specify a version" >&2 exit 1 fi # .rockspec cp luv-scm-0.rockspec luv-${version}.rockspec cp rockspecs/luv-scm-0.rockspec rockspecs/luv-${version}.rockspec script="/^version/s@\"[^\"]\\+\"@\"${version}\"@" sed -e "${script}" -i luv-${version}.rockspec sed -e "${script}" -i rockspecs/luv-${version}.rockspec script="s@git://github.com/luvit/luv.git@https://github.com/luvit/luv/releases/download/'..version..'/luv-'..version..'.tar.gz@" sed -e "${script}" -i luv-${version}.rockspec sed -e "${script}" -i rockspecs/luv-${version}.rockspec # .tar.gz rm -rf luv-${version} mkdir -p luv-${version}/deps cp -r src cmake CMakeLists.txt LICENSE.txt README.md docs.md libluv.pc.in luv-${version}/ cp -r deps/libuv deps/lua-compat-5.3 deps/*.cmake deps/lua_one.c luv-${version}/deps/ COPYFILE_DISABLE=true tar -czvf luv-${version}.tar.gz luv-${version} rm -rf luv-${version} luv-1.36.0-0/.ci/platform.sh000066400000000000000000000003711364617304100154030ustar00rootroot00000000000000if [ -z "${PLATFORM:-}" ]; then PLATFORM=$TRAVIS_OS_NAME; fi if [ "$PLATFORM" == "osx" ]; then PLATFORM="macosx"; fi if [ -z "$PLATFORM" ]; then if [ "$(uname)" == "Linux" ]; then PLATFORM="linux"; else PLATFORM="macosx"; fi; fi luv-1.36.0-0/.ci/set_compiler_env.bat000066400000000000000000000023641364617304100172540ustar00rootroot00000000000000@echo off :: Now we declare a scope Setlocal EnableDelayedExpansion EnableExtensions if not defined COMPILER set COMPILER=%APPVEYOR_BUILD_WORKER_IMAGE:~14,4% if "%COMPILER%"=="MinGW" ( goto :mingw ) set arch=x86 if "%platform%" EQU "x64" ( set arch=x86_amd64 ) if "%COMPILER%"=="2019" ( set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" ) if "%COMPILER%"=="2017" ( set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" ) if "%COMPILER%"=="2015" ( set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" ) if "%COMPILER%"=="2013" ( set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" ) if "%COMPILER%"=="2012" ( set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" ) if "%COMPILER%"=="2010" ( set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" ) if "%COMPILER%"=="2008" ( set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" ) :: Visual Studio detected endlocal & call %SET_VS_ENV% %arch% goto :eof :: MinGW detected :mingw endlocal & set PATH=c:\mingw\bin;%PATH% luv-1.36.0-0/.ci/setenv_lua.sh000066400000000000000000000002341364617304100157220ustar00rootroot00000000000000export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/luarocks/bin bash .ci/setup_lua.sh || exit eval "$("$HOME/.lua/luarocks" path)" luv-1.36.0-0/.ci/setup_lua.sh000066400000000000000000000061221364617304100155600ustar00rootroot00000000000000#!/usr/bin/env bash # A script for setting up environment for travis-ci testing. # Sets up Lua and Luarocks. # LUA must be "lua5.1", "lua5.2" or "luajit". # luajit2.0 - master v2.0 # luajit2.1 - master v2.1 set -eufxo pipefail LUAJIT_VERSION="2.0.4" LUAJIT_BASE="LuaJIT-$LUAJIT_VERSION" source .ci/platform.sh LUA_HOME_DIR=$TRAVIS_BUILD_DIR/install/lua LR_HOME_DIR=$TRAVIS_BUILD_DIR/install/luarocks mkdir "$HOME/.lua" LUAJIT="no" if [ "$PLATFORM" == "macosx" ]; then if [ "$LUA" == "luajit" ]; then LUAJIT="yes"; fi if [ "$LUA" == "luajit2.0" ]; then LUAJIT="yes"; fi if [ "$LUA" == "luajit2.1" ]; then LUAJIT="yes"; fi; elif [ "$(expr substr $LUA 1 6)" == "luajit" ]; then LUAJIT="yes"; fi mkdir -p "$LUA_HOME_DIR" if [ "$LUAJIT" == "yes" ]; then if [ "$LUA" == "luajit" ]; then curl --silent --location https://github.com/LuaJIT/LuaJIT/archive/v$LUAJIT_VERSION.tar.gz | tar xz; else git clone -q https://github.com/LuaJIT/LuaJIT.git $LUAJIT_BASE; fi cd $LUAJIT_BASE if [ "$LUA" == "luajit2.1" ]; then git checkout v2.1; # force the INSTALL_TNAME to be luajit perl -i -pe 's/INSTALL_TNAME=.+/INSTALL_TNAME= luajit/' Makefile fi make && make install PREFIX="$LUA_HOME_DIR" ln -s "$LUA_HOME_DIR/bin/luajit" "$HOME/.lua/luajit" ln -s "$LUA_HOME_DIR/bin/luajit" "$HOME/.lua/lua" else if [ "$LUA" == "lua5.1" ]; then curl --silent https://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz cd lua-5.1.5; elif [ "$LUA" == "lua5.2" ]; then curl --silent https://www.lua.org/ftp/lua-5.2.4.tar.gz | tar xz cd lua-5.2.4; elif [ "$LUA" == "lua5.3" ]; then curl --silent https://www.lua.org/ftp/lua-5.3.2.tar.gz | tar xz cd lua-5.3.2; fi # Build Lua without backwards compatibility for testing perl -i -pe 's/-DLUA_COMPAT_(ALL|5_2)//' src/Makefile make "$PLATFORM" make INSTALL_TOP="$LUA_HOME_DIR" install; ln -s "$LUA_HOME_DIR/bin/lua" "$HOME/.lua/lua" ln -s "$LUA_HOME_DIR/bin/luac" "$HOME/.lua/luac" fi cd "$TRAVIS_BUILD_DIR" lua -v LUAROCKS_BASE=luarocks-$LUAROCKS # retry 5 times, connection to luarocks.org seems to timeout occassionally curl --silent --location --retry 5 "https://luarocks.org/releases/$LUAROCKS_BASE.tar.gz" | tar xz cd "$LUAROCKS_BASE" configure_args=("--prefix=$LR_HOME_DIR" "--with-lua=$LUA_HOME_DIR") if [ "${LUA#luajit}" != "$LUA" ]; then # LuaJIT if [ "${LUAROCKS#2.}" != "${LUAROCKS}" ]; then configure_args+=('--lua-suffix=jit') if [ "$LUA" = luajit ]; then luajit_ver=2.0 else luajit_ver=${LUA#luajit} fi configure_args+=("--with-lua-include=$LUA_HOME_DIR/include/luajit-${luajit_ver}") else configure_args+=('--with-lua-interpreter=luajit') fi fi ./configure "${configure_args[@]}" make build && make install ln -s "$LR_HOME_DIR/bin/luarocks" "$HOME/.lua/luarocks" cd "$TRAVIS_BUILD_DIR" luarocks --version rm -rf "$LUAROCKS_BASE" if [ "$LUAJIT" == "yes" ]; then rm -rf $LUAJIT_BASE; elif [ "$LUA" == "lua5.1" ]; then rm -rf lua-5.1.5; elif [ "$LUA" == "lua5.2" ]; then rm -rf lua-5.2.4; elif [ "$LUA" == "lua5.3" ]; then rm -rf lua-5.3.2; fi luv-1.36.0-0/.ci/setup_min_libuv.sh000077500000000000000000000007771364617304100170000ustar00rootroot00000000000000#!/usr/bin/env bash # A script for setting up environment for travis-ci testing. # Sets up the minimum supported Libuv version for testing # backwards compatibility of Luv set -eufxo pipefail LIBUV_VERSION="1.0.0" LIBUV_BASE="libuv-$LIBUV_VERSION" INSTALL_DIR="$HOME/.libuv_min" mkdir "$INSTALL_DIR" source .ci/platform.sh curl --silent --location https://github.com/libuv/libuv/archive/v$LIBUV_VERSION.tar.gz | tar xz; cd $LIBUV_BASE; sh autogen.sh ./configure --prefix "$INSTALL_DIR" make make install luv-1.36.0-0/.ci/winmake.bat000066400000000000000000000317741364617304100153610ustar00rootroot00000000000000@ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION REM ***************************** REM * Customization section * REM ***************************** REM use the /help option for generic usage information REM Where is the source code located (the unpacked Lua source archive, toplevel dir) SET SOURCETREE=.\ REM set the toolchain to either MS or GCC (allcaps), leave blank to autodetect SET TOOLCHAIN= REM set the compatibility flags, defaults to empty for 5.1, -DLUA_COMPAT_ALL for 5.2, REM and -DLUA_COMPAT_5_2 for 5.3, which are the same as the unix make files REM This setting can be overridden with the --nocompat flag SET COMPATFLAG= REM ********************************** REM * Nothing to customize below * REM ********************************** SET BATCHNAME=%~n0 SET SOURCE=%SOURCETREE%src\ SET LUA_H=%SOURCE%lua.h SET CURDIR=%CD% REM the following line ends with a TAB. DO NOT REMOVE IT! SET TABCHAR= REM Define LF to contain a linefeed character set ^"LFCHAR=^ ^" The above empty line is critical. DO NOT REMOVE REM Supported toolchains (allcaps) SET TOOLCHAINS=MS GCC REM Commands which, if exiting without error, indicate presence of the toolchain SET CHECK_GCC=gcc --version SET CHECK_MS=cl REM ********************************** REM * Check for help request * REM ********************************** SET HELPCMDS=help -help --help /help ? -? /? for %%L in ("!LFCHAR!") do for /f %%a in ("!HELPCMDS: =%%~L!") do ( if "%%a"=="%~1" ( echo. echo Builds a standalone Lua installation. Supports Lua version 5.1, 5.2 and 5.3. echo Your compiler must be in the system path, and this "%BATCHNAME%.bat" file must be located echo in ".\etc\" in the unpacked Lua source archive. echo. echo USAGE etc\%BATCHNAME% [FLAG] [COMMAND] [...] echo ^(execute from the root of the unpacked archive^) echo. echo Commands; echo clean : cleans the source tree of build ^(intermediate^) files echo install [path] : installs the build results into "path" echo local : installs into ".\local\" in the unpacked Lua source structure echo [toolchain] : uses a specific toolchain to build. If not provided then supported echo toolchains will be tested and the first available will be picked. echo Supported toolchains are: "%TOOLCHAINS%" ^(must use ALLCAPS^) echo. echo Flags; echo --nocompat : Specifies that no compatibility flags should be set when building. echo If not specified, the default compatibility flags will be used. echo. echo Example use; echo set PATH=C:\path\to\your\compiler\;%%PATH%% echo etc\%BATCHNAME% clean echo etc\%BATCHNAME% echo etc\%BATCHNAME% --nocompat GCC echo etc\%BATCHNAME% install "C:\Program Files\Lua" echo. goto :EXITOK ) ) REM ********************************** REM * Check commandline * REM ********************************** SET CMDOK=FALSE if "%~1"=="" ( SET CMDOK=TRUE ) for %%a in (local install clean) do ( if "%%a"=="%~1" ( SET CMDOK=TRUE ) ) for %%a in (--nocompat) do ( if "%%a"=="%~1" ( SET NOCOMPAT=TRUE if "%~2"=="" ( SET CMDOK=TRUE ) SHIFT ) ) for %%a in (%TOOLCHAINS%) do ( if "%%a"=="%~1" ( SET CMDOK=TRUE SET TOOLCHAIN=%~1 ) ) if NOT %CMDOK%==TRUE ( echo. echo Unknown command or toolchain specified. goto :EXITERROR ) REM ************************************** REM * Check for cleaning * REM ************************************** if "%1"=="clean" ( if NOT [%2]==[] ( echo. echo ERROR: The clean command does not take extra parameters. ) else ( echo Cleaning... if exist "%SOURCE%*.exe" del "%SOURCE%*.exe" if exist "%SOURCE%*.dll" del "%SOURCE%*.dll" if exist "%SOURCE%*.o" del "%SOURCE%*.o" if exist "%SOURCE%*.a" del "%SOURCE%*.a" if exist "%SOURCE%*.obj" del "%SOURCE%*.obj" if exist "%SOURCE%*.manifest" del "%SOURCE%*.manifest" if exist "%SOURCE%*.lib" del "%SOURCE%*.lib" echo Done. ) goto :EXITOK ) REM ************************************************** REM * Fetch the Lua version from the source code * REM ************************************************** Echo. Echo Checking source code to extract Lua version... IF NOT EXIST %LUA_H% ( Echo Cannot locate Lua header file; %LUA_H% goto :EXITERROR ) findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MAJOR" %LUA_H% > NUL if NOT %ERRORLEVEL%==0 ( rem ECHO We've got a Lua version 5.1 rem findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION[ %TABCHAR%]" %LUA_H% SET LUA_VER=5.1 ) else ( rem ECHO We've got a Lua version 5.2+ rem findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MAJOR[ %TABCHAR%]" %LUA_H% rem findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MINOR[ %TABCHAR%]" %LUA_H% for /F "delims=" %%a in ('findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MAJOR[ %TABCHAR%]" %LUA_H%') do set LUA_MAJOR=%%a SET LUA_MAJOR=!LUA_MAJOR:#define=! SET LUA_MAJOR=!LUA_MAJOR:LUA_VERSION_MAJOR=! SET LUA_MAJOR=!LUA_MAJOR: =! SET LUA_MAJOR=!LUA_MAJOR:%TABCHAR%=! SET LUA_MAJOR=!LUA_MAJOR:"=! SET LUA_MAJOR=!LUA_MAJOR:~0,1! for /F "delims=" %%a in ('findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MINOR[ %TABCHAR%]" %LUA_H%') do set LUA_MINOR=%%a SET LUA_MINOR=!LUA_MINOR:#define=! SET LUA_MINOR=!LUA_MINOR:LUA_VERSION_MINOR=! SET LUA_MINOR=!LUA_MINOR: =! SET LUA_MINOR=!LUA_MINOR:%TABCHAR%=! SET LUA_MINOR=!LUA_MINOR:"=! SET LUA_MINOR=!LUA_MINOR:~0,1! SET LUA_VER=!LUA_MAJOR!.!LUA_MINOR! ) SET LUA_SVER=!LUA_VER:.=! Echo Lua version found: %LUA_VER% Echo. REM ************************************** REM * Set some Lua version specifics * REM ************************************** REM FILES_CORE; files for Lua core (+lauxlib, needed for Luac) REM FILES_LIB; files for Lua standard libraries REM FILES_DLL; vm files to be build with dll option REM FILES_OTH; vm files to be build without dll, for static linking if %LUA_SVER%==51 ( set FILES_CORE=lapi lcode ldebug ldo ldump lfunc lgc llex lmem lobject lopcodes lparser lstate lstring ltable ltm lundump lvm lzio lauxlib set FILES_LIB=lbaselib ldblib liolib lmathlib loslib ltablib lstrlib loadlib linit set FILES_DLL=lua set FILES_OTH=luac print set INSTALL_H=lauxlib.h lua.h luaconf.h lualib.h ..\etc\lua.hpp ) if %LUA_SVER%==52 ( set FILES_CORE=lapi lcode lctype ldebug ldo ldump lfunc lgc llex lmem lobject lopcodes lparser lstate lstring ltable ltm lundump lvm lzio lauxlib set FILES_LIB=lbaselib lbitlib lcorolib ldblib liolib lmathlib loslib lstrlib ltablib loadlib linit set FILES_DLL=lua set FILES_OTH=luac set INSTALL_H=lauxlib.h lua.h lua.hpp luaconf.h lualib.h if "%COMPATFLAG%"=="" ( set COMPATFLAG=-DLUA_COMPAT_ALL ) ) if %LUA_SVER%==53 ( set FILES_CORE=lapi lcode lctype ldebug ldo ldump lfunc lgc llex lmem lobject lopcodes lparser lstate lstring ltable ltm lundump lvm lzio lauxlib set FILES_LIB=lbaselib lbitlib lcorolib ldblib liolib lmathlib loslib lstrlib ltablib lutf8lib loadlib linit set FILES_DLL=lua set FILES_OTH=luac set INSTALL_H=lauxlib.h lua.h lua.hpp luaconf.h lualib.h if "%COMPATFLAG%"=="" ( set COMPATFLAG=-DLUA_COMPAT_5_2 ) ) if "%NOCOMPAT%"=="TRUE" ( set COMPATFLAG= ) SET FILES_BASE=%FILES_DLL% %FILES_CORE% %FILES_LIB% if "%FILES_BASE%"=="" ( Echo Unknown Lua version; %LUA_VER% goto :EXITERROR ) REM ********************************* REM * Check available toolchain * REM ********************************* if [%TOOLCHAIN%]==[] ( Echo Testing for MS... %CHECK_MS% IF !ERRORLEVEL!==0 SET TOOLCHAIN=MS ) if [%TOOLCHAIN%]==[] ( Echo Testing for GCC... %CHECK_GCC% IF !ERRORLEVEL!==0 SET TOOLCHAIN=GCC ) if [%TOOLCHAIN%]==[] ( Echo No supported toolchain found ^(please make sure it is in the system path^) goto :EXITERROR ) REM *************************** REM * Configure toolchain * REM *************************** if %TOOLCHAIN%==GCC ( echo Using GCC toolchain... SET OBJEXT=o SET LIBFILE=liblua%LUA_SVER%.a ) if %TOOLCHAIN%==MS ( echo Using Microsoft toolchain... SET OBJEXT=obj SET LIBFILE=lua%LUA_SVER%.lib ) echo. REM ************************************** REM * Check for installing * REM ************************************** if "%1"=="install" ( if "%~2"=="" ( echo. echo ERROR: The install command requires a path where to install to. goto :EXITERROR ) SET TARGETPATH=%~2 ) if "%1"=="local" ( if NOT "%~2"=="" ( echo. echo ERROR: The local command does not take extra parameters. goto :EXITERROR ) SET TARGETPATH=%SOURCETREE%local ) if NOT "%TARGETPATH%"=="" ( mkdir "%TARGETPATH%\bin" mkdir "%TARGETPATH%\include" mkdir "%TARGETPATH%\lib\lua\%LUA_VER%" mkdir "%TARGETPATH%\man\man1" mkdir "%TARGETPATH%\share\lua\%LUA_VER%" copy "%SOURCE%lua.exe" "%TARGETPATH%\bin" copy "%SOURCE%luac.exe" "%TARGETPATH%\bin" copy "%SOURCE%lua%LUA_SVER%.dll" "%TARGETPATH%\bin" for %%a in (%INSTALL_H%) do ( copy "%SOURCE%%%a" "%TARGETPATH%\include" ) copy "%SOURCE%%LIBFILE%" "%TARGETPATH%\lib" copy "%SOURCETREE%doc\lua.1" "%TARGETPATH%\man\man1" copy "%SOURCETREE%doc\luac.1" "%TARGETPATH%\man\man1" echo Installation completed in "%TARGETPATH%". goto :EXITOK ) REM *********************** REM * Compile sources * REM *********************** goto :after_compile_function :compile_function REM Params: %1 is filelist (must be quoted) REM Return: same list, with the object file extension included, will be stored in global OBJLIST for %%a in (%~1) do ( SET FILENAME=%%a if %TOOLCHAIN%==GCC ( SET COMPCMD=gcc -O2 -Wall !EXTRAFLAG! !COMPATFLAG! -c -o !FILENAME!.%OBJEXT% !FILENAME!.c ) if %TOOLCHAIN%==MS ( SET COMPCMD=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE !COMPATFLAG! !EXTRAFLAG! !FILENAME!.c ) echo !COMPCMD! !COMPCMD! SET OBJLIST=!OBJLIST! !FILENAME!.%OBJEXT% ) goto :eof :after_compile_function CD %SOURCE% REM Traverse the 4 lists of source files for %%b in (CORE LIB DLL OTH) do ( SET LTYPE=%%b SET OBJLIST= if !LTYPE!==OTH ( REM OTH is the only list of files build without DLL option SET EXTRAFLAG= ) else ( SET EXTRAFLAG=-DLUA_BUILD_AS_DLL ) if !LTYPE!==CORE SET FILELIST=%FILES_CORE% if !LTYPE!==LIB SET FILELIST=%FILES_LIB% if !LTYPE!==DLL SET FILELIST=%FILES_DLL% if !LTYPE!==OTH SET FILELIST=%FILES_OTH% echo Now compiling !LTYPE! file set... call:compile_function "!FILELIST!" if !LTYPE!==CORE SET FILES_CORE_O=!OBJLIST! if !LTYPE!==LIB SET FILES_LIB_O=!OBJLIST! if !LTYPE!==DLL SET FILES_DLL_O=!OBJLIST! if !LTYPE!==OTH SET FILES_OTH_O=!OBJLIST! ) REM **************************** REM * Link GCC based files * REM **************************** if %TOOLCHAIN%==GCC ( REM Link the LuaXX.dll file SET LINKCMD=gcc -shared -o lua%LUA_SVER%.dll %FILES_CORE_O% %FILES_LIB_O% echo !LINKCMD! !LINKCMD! REM strip from LuaXX.dll SET RANCMD=strip --strip-unneeded lua%LUA_SVER%.dll echo !RANCMD! !RANCMD! REM Link the Lua.exe file SET LINKCMD=gcc -o lua.exe -s lua.%OBJEXT% lua%LUA_SVER%.dll -lm echo !LINKCMD! !LINKCMD! REM create lib archive SET LIBCMD=ar rcu liblua%LUA_SVER%.a %FILES_CORE_O% %FILES_LIB_O% echo !LIBCMD! !LIBCMD! REM Speedup index using ranlib SET RANCMD=ranlib liblua%LUA_SVER%.a echo !RANCMD! !RANCMD! REM Link Luac.exe file SET LINKCMD=gcc -o luac.exe %FILES_OTH_O% liblua%LUA_SVER%.a -lm echo !LINKCMD! !LINKCMD! ) REM **************************** REM * Link MS based files * REM **************************** if %TOOLCHAIN%==MS ( REM Link the LuaXX.dll file, and LuaXX.obj SET LINKCMD=link /nologo /DLL /out:lua%LUA_SVER%.dll %FILES_CORE_O% %FILES_LIB_O% echo !LINKCMD! !LINKCMD! REM handle dll manifest if exist lua%LUA_SVER%.dll.manifest ( SET MANICMD=mt /nologo -manifest lua%LUA_SVER%.dll.manifest -outputresource:lua%LUA_SVER%.dll;2 echo !MANICMD! !MANICMD! ) REM Link Lua.exe SET LINKCMD=link /nologo /out:lua.exe lua.%OBJEXT% lua%LUA_SVER%.lib echo !LINKCMD! !LINKCMD! REM handle manifest if exist lua.exe.manifest ( SET MANICMD=mt /nologo -manifest lua.exe.manifest -outputresource:lua.exe echo !MANICMD! !MANICMD! ) REM Link Luac.exe SET LINKCMD=link /nologo /out:luac.exe %FILES_OTH_O% %FILES_CORE_O% echo !LINKCMD! !LINKCMD! REM handle manifest if exist luac.exe.manifest ( SET MANICMD=mt /nologo -manifest luac.exe.manifest -outputresource:luac.exe echo !MANICMD! !MANICMD! ) ) CD %CURDIR% REM **************************** REM * Finished building * REM **************************** echo. echo Build completed. goto :EXITOK :EXITOK exit /B 0 :EXITERROR echo For help try; etc\%BATCHNAME% /help exit /B 1 luv-1.36.0-0/.editorconfig000066400000000000000000000002121364617304100152210ustar00rootroot00000000000000# http://editorconfig.org root = true [*.{c,h,lua}] indent_style = space indent_size = 2 charset = utf-8 trim_trailing_whitespace = true luv-1.36.0-0/.gitignore000066400000000000000000000001461364617304100145420ustar00rootroot00000000000000build libluv.a libluv.so luv.so luv.dll luajit.exe luv-*.tar.gz luv-*.src.rock luv-*/ build.luarocks/ luv-1.36.0-0/.gitmodules000066400000000000000000000005371364617304100147330ustar00rootroot00000000000000[submodule "libuv"] path = deps/libuv url = https://github.com/libuv/libuv.git [submodule "luajit"] path = deps/luajit url = https://github.com/LuaJIT/LuaJIT.git [submodule "lua"] path = deps/lua url = https://github.com/lua/lua [submodule "lua-compat-5.3"] path = deps/lua-compat-5.3 url = https://github.com/keplerproject/lua-compat-5.3.git luv-1.36.0-0/.travis.yml000066400000000000000000000060631364617304100146670ustar00rootroot00000000000000language: c sudo: false addons: apt: sources: - kalakris-cmake packages: - cmake env: global: - LUAROCKS=2.3.0 # For LuaJIT 2.1, see https://github.com/LuaJIT/LuaJIT/commit/8961a92dd1607108760694af3486b4434602f8be - MACOSX_DEPLOYMENT_TARGET=10.12 matrix: - WITH_LUA_ENGINE=Lua LUA=lua5.3 - WITH_LUA_ENGINE=LuaJIT LUA=luajit2.1 # LuaRocks 3.1.3 - LUAROCKS=3.1.3 WITH_LUA_ENGINE=Lua LUA=lua5.3 - LUAROCKS=3.1.3 WITH_LUA_ENGINE=LuaJIT LUA=luajit2.1 os: - linux - osx script: - make && make test # Setup LuaRocks - source .ci/setenv_lua.sh # Test rock installation - luarocks make - test $PWD = `lua -e "print(require'luv'.cwd())"` - luarocks remove luv # Test the alternate rockspec - mkdir build/lib - cp build/deps/libuv/libuv_a.a build/lib/libuv.a - cp -a deps/libuv/include build - luarocks make rockspecs/$(ls rockspecs) LIBUV_DIR=build LUA_COMPAT53_INCDIR=deps/lua-compat-5.3/c-api - test $PWD = `lua -e "print(require'luv'.cwd())"` jobs: fast_finish: true include: - stage: check name: bindings coverage addons: apt: # don't need cmake for this one os: linux script: - ./.ci/bindcov.sh - name: clang-asan os: linux compiler: clang env: - ASAN_OPTIONS="detect_leaks=1:check_initialization_order=1" - UBSAN_OPTIONS="print_stacktrace=1" - BUILD_TYPE=Debug - WITH_LUA_ENGINE=Lua script: - CMAKE_OPTIONS="-DCMAKE_C_FLAGS=-fsanitize=address,undefined" make && make test - name: valgrind os: linux # Need a more up-to-date Valgrind to dodge https://bugs.kde.org/show_bug.cgi?id=381289 dist: bionic addons: apt: packages: - valgrind env: - BUILD_TYPE=Debug - WITH_LUA_ENGINE=Lua script: - make - valgrind --error-exitcode=1 --leak-check=full --child-silent-after-fork=yes ./build/lua tests/run.lua - name: process cleanup test os: linux env: - WITH_LUA_ENGINE=Lua script: - ./tests/test-sigchld-after-lua_close.sh - name: minimum supported libuv os: linux env: - WITH_LUA_ENGINE=Lua - WITH_SHARED_LIBUV=On script: - ./.ci/setup_min_libuv.sh - CMAKE_OPTIONS="-DCMAKE_PREFIX_PATH=$HOME/.libuv_min" make && make test - stage: deploy if: tag IS present env: WITH_LUA_ENGINE=LuaJIT LUA=luajit2.1 script: skip before_deploy: # Setup LuaRocks - source .ci/setenv_lua.sh - .ci/make_rockspec.sh $TRAVIS_TAG deploy: provider: releases api_key: $GITHUB_OAUTH_TOKEN file: luv-$TRAVIS_TAG.tar.gz overwrite: true skip_cleanup: true on: tags: true after_deploy: - luarocks install lua-cjson # required for luarocks upload - luarocks upload luv-$TRAVIS_TAG.rockspec --api-key=$LUAROCKS_API_KEY --force stages: - check - test - deploy notifications: email: true irc: "irc.freenode.org#luvit" luv-1.36.0-0/CMakeLists.txt000066400000000000000000000205261364617304100153160ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8) if(POLICY CMP0053) cmake_policy(SET CMP0053 NEW) # faster evaluation of variable references endif() project (luv C ASM) set(LUV_VERSION_MAJOR 1) set(LUV_VERSION_MINOR 36) set(LUV_VERSION_PATCH 0) set(LUV_VERSION ${LUV_VERSION_MAJOR}.${LUV_VERSION_MINOR}.${LUV_VERSION_PATCH}) option(BUILD_MODULE "Build as module" ON) option(BUILD_STATIC_LIBS "Build static library" OFF) option(BUILD_SHARED_LIBS "Build shared library" OFF) option(WITH_SHARED_LIBUV "Link to a shared libuv library instead of static linking" OFF) if (MINGW) add_definitions(-D_WIN32_WINNT=0x0600) endif (MINGW) if (WIN32) # replace /MD to /MT to avoid link msvcr*.dll # this needs to be before add_subdirectory calls so that they inherit the modified flags set(CompilerFlags CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_RELEASE) foreach(CompilerFlag ${CompilerFlags}) string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") endforeach() endif () if (NOT WITH_LUA_ENGINE) set(WITH_LUA_ENGINE "LuaJIT" CACHE STRING "Link to LuaJIT or PUC Lua" FORCE) set_property(CACHE WITH_LUA_ENGINE PROPERTY STRINGS "Lua;LuaJIT") endif (NOT WITH_LUA_ENGINE) if (NOT LUA_BUILD_TYPE) set(LUA_BUILD_TYPE "Static" CACHE STRING "Build Lua/LuaJIT as static, dynamic libary, or use system one" FORCE) set_property(CACHE LUA_BUILD_TYPE PROPERTY STRINGS "Static;Dynamic;System") endif (NOT LUA_BUILD_TYPE) if (WITH_LUA_ENGINE STREQUAL Lua) if (NOT WIN32) add_definitions(-DLUA_USE_DLOPEN) endif (NOT WIN32) set(USE_LUAJIT OFF) else () set(USE_LUAJIT ON) endif () set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") if (WITH_SHARED_LIBUV) find_package(Libuv REQUIRED) include_directories(${LIBUV_INCLUDE_DIR}) else (WITH_SHARED_LIBUV) include_directories(deps/libuv/include) add_subdirectory(deps/libuv EXCLUDE_FROM_ALL) if (BUILD_MODULE) add_definitions( -DBUILDING_UV_SHARED ) endif (BUILD_MODULE) set(LIBUV_LIBRARIES uv_a) set_target_properties(uv_a PROPERTIES COMPILE_FLAGS "-fPIC") endif (WITH_SHARED_LIBUV) if (LUA) MESSAGE(STATUS "Lua: using information from luarocks") MESSAGE(STATUS "LUA_LIBDIR: " ${LUA_LIBDIR}) MESSAGE(STATUS "LUA_INCDIR: " ${LUA_INCDIR}) MESSAGE(STATUS "LUA: " ${LUA}) SET(LUA_EXECUTABLE "${LUA}") SET(LUA_INCLUDE_DIR "${LUA_INCDIR}") SET(LUA_PACKAGE_PATH "${LUADIR}") SET(LUA_PACKAGE_CPATH "${LIBDIR}") SET(INSTALL_LIB_DIR ${LIBDIR}) GET_FILENAME_COMPONENT(LUA_EXEC_NAME ${LUA_EXECUTABLE} NAME_WE) IF(LUA_EXEC_NAME STREQUAL "luajit") FIND_LIBRARY(LUA_LIBRARIES NAMES luajit libluajit PATHS ${LUA_LIBDIR} NO_DEFAULT_PATH) ELSEIF(LUA_EXEC_NAME MATCHES "lua.*") FIND_LIBRARY(LUA_LIBRARIES NAMES lua lua53 lua52 lua51 liblua liblua53 liblua52 liblua51 PATHS ${LUA_LIBDIR} NO_DEFAULT_PATH) ENDIF() MESSAGE(STATUS "Lua library: ${LUA_LIBRARIES}") include_directories(${LUA_INCLUDE_DIR}) else (LUA) if (LUA_BUILD_TYPE STREQUAL System) if (USE_LUAJIT) find_package(LuaJIT REQUIRED) include_directories(${LUAJIT_INCLUDE_DIR}) link_directories(${LUAJIT_LIBRARIES}) else (USE_LUAJIT) find_package(Lua REQUIRED) include_directories(${LUA_INCLUDE_DIR}) endif (USE_LUAJIT) else (LUA_BUILD_TYPE STREQUAL System) if (LUA_BUILD_TYPE STREQUAL Static) SET(WITH_SHARED_LUA OFF) else (LUA_BUILD_TYPE STREQUAL Static) SET(WITH_SHARED_LUA ON) endif (LUA_BUILD_TYPE STREQUAL Static) if (USE_LUAJIT) include(deps/luajit.cmake) include_directories(deps/luajit/src) set(LUAJIT_LIBRARIES luajit-5.1) else(USE_LUAJIT) include(deps/lua.cmake) include_directories(deps/lua) endif (USE_LUAJIT) endif (LUA_BUILD_TYPE STREQUAL System) endif (LUA) if (BUILD_MODULE) add_library(luv MODULE src/luv.c) set_target_properties(luv PROPERTIES PREFIX "") list(APPEND ACTIVE_TARGETS "luv") endif (BUILD_MODULE) if (BUILD_STATIC_LIBS) add_library(libluv_a STATIC src/luv.c) set_target_properties(libluv_a PROPERTIES PREFIX "") list(APPEND ACTIVE_TARGETS "libluv_a") endif (BUILD_STATIC_LIBS) if (BUILD_SHARED_LIBS) add_library(libluv SHARED src/luv.c) set_target_properties(libluv PROPERTIES PREFIX "") set_target_properties(libluv PROPERTIES VERSION ${LUV_VERSION} SOVERSION ${LUV_VERSION_MAJOR}) list(APPEND ACTIVE_TARGETS "libluv") endif (BUILD_SHARED_LIBS) if(APPLE) set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress" ) # execute_process(COMMAND which luajit OUTPUT_VARIABLE LUAJIT) # set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS # "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -bundle_loader ${LUAJIT}" # ) endif() if(NOT LUA_COMPAT53_DIR) set(LUA_COMPAT53_DIR deps/lua-compat-5.3) endif() if(DEFINED ENV{LUA_COMPAT53_DIR}) set(LUA_COMPAT53_DIR $ENV{LUA_COMPAT53_DIR}) endif() include_directories(${LUA_COMPAT53_DIR}/c-api) if(WIN32) add_definitions(-DLUA_BUILD_AS_DLL -DLUA_LIB) endif() foreach(TARGET_NAME ${ACTIVE_TARGETS}) if(WIN32) if (LUA) target_link_libraries(${TARGET_NAME} ${LIBUV_LIBRARIES} ${LUA_LIBRARIES}) else (LUA) if (USE_LUAJIT) target_link_libraries(${TARGET_NAME} ${LIBUV_LIBRARIES} ${LUAJIT_LIBRARIES}) else (USE_LUAJIT) if (LUA_BUILD_TYPE STREQUAL System) target_link_libraries(${TARGET_NAME} ${LIBUV_LIBRARIES} ${LUA_LIBRARIES}) else (LUA_BUILD_TYPE STREQUAL System) target_link_libraries(${TARGET_NAME} ${LIBUV_LIBRARIES} lualib) endif (LUA_BUILD_TYPE STREQUAL System) endif (USE_LUAJIT) endif (LUA) elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") target_link_libraries(${TARGET_NAME} ${LIBUV_LIBRARIES} rt) else() target_link_libraries(${TARGET_NAME} ${LIBUV_LIBRARIES}) endif() endforeach() if (NOT LUA) if (BUILD_MODULE) if (WIN32) set(MODULE_INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") else (WIN32) set(MODULE_INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib/lua/${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}") endif (WIN32) endif (BUILD_MODULE) if (BUILD_STATIC_LIBS) set(STATICLIBS_INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for static libraries") endif (BUILD_STATIC_LIBS) if (BUILD_SHARED_LIBS) set(SHAREDLIBS_INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for shared libraries") endif (BUILD_SHARED_LIBS) else () # use paths from luaRocks set(MODULE_INSTALL_LIB_DIR "${INSTALL_LIB_DIR}") set(STATICLIBS_INSTALL_LIB_DIR "${INSTALL_LIB_DIR}") set(SHAREDLIBS_INSTALL_LIB_DIR "${INSTALL_LIB_DIR}") endif () # header install paths are LuaRocks-agnostic, so just use CMAKE_INSTALL_PREFIX regardless if (BUILD_STATIC_LIBS) set(STATICLIBS_INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include/luv" CACHE PATH "Installation directory for headers") endif (BUILD_STATIC_LIBS) if (BUILD_SHARED_LIBS) set(SHAREDLIBS_INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include/luv" CACHE PATH "Installation directory for headers") endif (BUILD_SHARED_LIBS) if (CMAKE_INSTALL_PREFIX) if (BUILD_MODULE) install(TARGETS luv ARCHIVE DESTINATION "${MODULE_INSTALL_LIB_DIR}" LIBRARY DESTINATION "${MODULE_INSTALL_LIB_DIR}" ) endif (BUILD_MODULE) if (BUILD_STATIC_LIBS) install(TARGETS libluv_a ARCHIVE DESTINATION "${STATICLIBS_INSTALL_LIB_DIR}" LIBRARY DESTINATION "${STATICLIBS_INSTALL_LIB_DIR}" ) install( FILES src/luv.h src/util.h src/lhandle.h src/lreq.h DESTINATION "${STATICLIBS_INSTALL_INC_DIR}" ) endif (BUILD_STATIC_LIBS) if (BUILD_SHARED_LIBS) install(TARGETS libluv ARCHIVE DESTINATION "${SHAREDLIBS_INSTALL_LIB_DIR}" LIBRARY DESTINATION "${SHAREDLIBS_INSTALL_LIB_DIR}" ) if(UNIX) set(prefix ${CMAKE_INSTALL_PREFIX}) set(includedir ${SHAREDLIBS_INSTALL_INC_DIR}) set(libdir ${SHAREDLIBS_INSTALL_LIB_DIR}) configure_file(libluv.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libluv.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libluv.pc DESTINATION ${SHAREDLIBS_INSTALL_LIB_DIR}/pkgconfig) endif() install( FILES src/luv.h src/util.h src/lhandle.h src/lreq.h DESTINATION "${SHAREDLIBS_INSTALL_INC_DIR}" ) endif (BUILD_SHARED_LIBS) endif (CMAKE_INSTALL_PREFIX) luv-1.36.0-0/LICENSE.txt000066400000000000000000000261361364617304100144040ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. luv-1.36.0-0/Makefile000066400000000000000000000034351364617304100142160ustar00rootroot00000000000000LUV_TAG=$(shell git describe --tags) ifdef WITHOUT_AMALG CMAKE_OPTIONS+= -DWITH_AMALG=OFF endif BUILD_MODULE ?= ON BUILD_SHARED_LIBS ?= OFF WITH_SHARED_LIBUV ?= OFF WITH_LUA_ENGINE ?= LuaJIT LUA_BUILD_TYPE ?= Static LUA_COMPAT53_DIR ?= deps/lua-compat-5.3 BUILD_DIR ?= build # options: Release, Debug, RelWithDebInfo, MinSizeRel BUILD_TYPE ?= RelWithDebInfo ifeq ($(WITH_LUA_ENGINE), LuaJIT) LUABIN=$(BUILD_DIR)/luajit else LUABIN=$(BUILD_DIR)/lua endif CMAKE_OPTIONS += \ -DBUILD_MODULE=$(BUILD_MODULE) \ -DBUILD_SHARED_LIBS=$(BUILD_SHARED_LIBS) \ -DWITH_SHARED_LIBUV=$(WITH_SHARED_LIBUV) \ -DWITH_LUA_ENGINE=$(WITH_LUA_ENGINE) \ -DLUA_BUILD_TYPE=$(LUA_BUILD_TYPE) \ -DLUA_COMPAT53_DIR=$(LUA_COMPAT53_DIR) \ -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) ifeq ($(MAKE),mingw32-make) CMAKE_OPTIONS += -G"MinGW Makefiles" LUV_EXT ?= .dll LUV_CP ?= cp -f endif LUV_EXT ?= .so LUV_CP ?= ln -sf all: luv deps/libuv/include: git submodule update --init deps/libuv deps/luajit/src: git submodule update --init deps/luajit deps/lua-compat-5.3/c-api: git submodule update --init deps/lua-compat-5.3 $(BUILD_DIR)/Makefile: deps/libuv/include deps/luajit/src deps/lua-compat-5.3/c-api cmake -H. -B$(BUILD_DIR) ${CMAKE_OPTIONS} luv: $(BUILD_DIR)/Makefile cmake --build $(BUILD_DIR) $(LUV_CP) $(BUILD_DIR)/luv$(LUV_EXT) luv$(LUV_EXT) install: luv $(MAKE) -C $(BUILD_DIR) install clean: rm -rf $(BUILD_DIR) luv$(LUV_EXT) test: luv ${LUABIN} tests/run.lua reset: git submodule update --init --recursive && \ git clean -f -d && \ git checkout . publish-luarocks: github-release upload --user luvit --repo luv --tag ${LUV_TAG} \ --file luv-${LUV_TAG}.tar.gz --name luv-${LUV_TAG}.tar.gz luarocks upload luv-${LUV_TAG}.rockspec --api-key=${LUAROCKS_TOKEN} # vim: ts=8 sw=8 noet tw=79 fen fdm=marker luv-1.36.0-0/README.md000066400000000000000000000141441364617304100140340ustar00rootroot00000000000000luv === [![Linux Build Status](https://travis-ci.org/luvit/luv.svg?branch=master)](https://travis-ci.org/luvit/luv) [![Windows Build status](https://ci.appveyor.com/api/projects/status/uo1qhdcc0vcqsiok/branch/master?svg=true)](https://ci.appveyor.com/project/racker-buildbot/luv/branch/master) [![Code Quality: Cpp](https://img.shields.io/lgtm/grade/cpp/g/luvit/luv.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/luvit/luv/context:cpp) [![Total Alerts](https://img.shields.io/lgtm/alerts/g/luvit/luv.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/luvit/luv/alerts) [libuv](https://github.com/libuv/libuv) bindings for [luajit](http://luajit.org/) and [lua](http://www.lua.org/) [5.1](http://www.lua.org/manual/5.1/manual.html)/ [5.2](http://www.lua.org/manual/5.2/manual.html)/ [5.3](http://www.lua.org/manual/5.3/manual.html). This library makes libuv available to lua scripts. It was made for the [luvit](http://luvit.io/) project but should usable from nearly any lua project. The library can be used by multiple threads at once. Each thread is assumed to load the library from a different `lua_State`. Luv will create a unique `uv_loop_t` for each state. You can't share uv handles between states/loops. - [Luv docs](docs.md) - [Libuv docs](http://docs.libuv.org/) ```lua local uv = require('luv') -- Create a handle to a uv_timer_t local timer = uv.new_timer() -- This will wait 1000ms and then continue inside the callback timer:start(1000, 0, function () -- timer here is the value we passed in before from new_timer. print ("Awake!") -- You must always close your uv handles or you'll leak memory -- We can't depend on the GC since it doesn't know enough about libuv. timer:close() end) print("Sleeping"); -- uv.run will block and wait for all events to run. -- When there are no longer any active handles, it will return uv.run() ``` Here is an example of an TCP echo server ```lua local uv = require('luv') local function create_server(host, port, on_connection) local server = uv.new_tcp() server:bind(host, port) server:listen(128, function(err) -- Make sure there was no problem setting up listen assert(not err, err) -- Accept the client local client = uv.new_tcp() server:accept(client) on_connection(client) end) return server end local server = create_server("0.0.0.0", 0, function (client) client:read_start(function (err, chunk) -- Crash on errors assert(not err, err) if chunk then -- Echo anything heard client:write(chunk) else -- When the stream ends, close the socket client:close() end end) end) print("TCP Echo server listening on port " .. server:getsockname().port) uv.run() ``` More examples can be found in the [examples](examples) and [tests](tests) folders. ## Luarocks Luv is available on Luarocks [here](https://luarocks.org/modules/creationix/luv). It can be installed via: ``` luarocks install luv ``` Note: To require `luv` using `require 'uv'` (to maintain compatibility with how luv is required in [luvi](https://github.com/luvit/luvi)) create a `uv.lua` with the contents: ``` return require 'luv' ``` ## Building From Source To build, first install your compiler tools. ### Get a Compiler On linux this probably means `gcc` and `make`. On Ubuntu, the `build-essential` package is good for this. On OSX, you probably want XCode which comes with `clang` and `make` and friends. For windows the free Visual Studio Express works. If you get the 2013 edition, make sure to get the `Windows Deskop` edition. The `Windows` version doesn't include a working C compiler. Make sure to run all of setup including getting a free license. ### Install CMake Now install Cmake. The version in `brew` on OSX or most Linux package managers is good. The version on Travis CI is too old and so I use a PPA there. On windows use the installer and make sure to add cmake to your command prompt path. ### Install Git If you haven't already, install git and make sure it's in your path. This comes with XCode on OSX. On Linux it's in your package manager. For windows, use the installer at . Make sure it's available to your windows command prompt. ### Clone the Code Now open a terminal and clone the code. For windows I recommend the special developer command prompt that came with Visual Studio. ``` git clone https://github.com/luvit/luv.git --recursive cd luv ``` ### Build the Code and Test On windows I wrote a small batch file that runs the correct cmake commands and copies the output files for easy access. ``` C:\Code\luv> msvcbuild.bat C:\Code\luv> luajit tests\run.lua ``` On unix systems, use the Makefile. ``` ~/Code/luv> make test ``` This will build luv as a module library. Module libraries are plugins that are not linked into other targets. #### Build with PUC Lua 5.3 By default luv is linked with LuaJIT 2.1.0-beta3. If you rather like to link luv with PUC Lua 5.3 you can run make with: ``` ~/Code/luv> WITH_LUA_ENGINE=Lua make ``` #### Build as static library If you want to build luv as a static library run make with: ``` ~/Code/luv> BUILD_MODULE=OFF make ``` This will create a static library `libluv.a`. #### Build as shared library If you want to build luv as a shared library run make with: ``` ~/Code/luv> BUILD_MODULE=OFF BUILD_SHARED_LIBS=ON make ``` This will create a shared library `libluv.so`. #### Build with shared libraries By default the build system will build luv with the supplied dependencies. These are: * libuv * LuaJIT or Lua However, if your target system has already one or more of these dependencies installed you can link `luv` against them. ##### Linking with shared libuv The default shared library name for libuv is `libuv`. To link against it use: ``` ~/Code/luv> WITH_SHARED_LIBUV=ON make ``` ##### Linking with shared LuaJIT The default shared library name for LuaJIT is `libluajit-5.1`. To link against it use: ``` ~/Code/luv> LUA_BUILD_TYPE=System make ``` ##### Linking with shared Lua 5.x The default shared library name for Lua 5.x is `liblua5.x`. To link against it use: ``` ~/Code/luv> LUA_BUILD_TYPE=System WITH_LUA_ENGINE=Lua make ``` luv-1.36.0-0/appveyor.yml000066400000000000000000000040171364617304100151430ustar00rootroot00000000000000image: - Visual Studio 2015 - Visual Studio 2017 - Visual Studio 2019 platform: - x86 - x64 environment: matrix: - FROM_DEPS: true # LuaRocks 3.x - LUA_VER: 5.3.2 NOCOMPAT: true # with compatibility flags disabled. LUAROCKS_VER: 3.1.3 - LJ_VER: 2.1 LUAROCKS_VER: 3.1.3 # LuaRocks 2.x - LUA_VER: 5.3.2 NOCOMPAT: true # with compatibility flags disabled. LUAROCKS_VER: 2.3.0 - LJ_VER: 2.1 LUAROCKS_VER: 2.3.0 matrix: fast_finish: true exclude: # Skip x86 for LuaRocks tests - platform: x86 LUAROCKS_VER: 3.1.3 - platform: x86 LUAROCKS_VER: 2.3.0 # Only test LuaRocks with MSVC 2017 - image: Visual Studio 2015 LUAROCKS_VER: 3.1.3 - image: Visual Studio 2015 LUAROCKS_VER: 2.3.0 - image: Visual Studio 2019 LUAROCKS_VER: 3.1.3 - image: Visual Studio 2019 LUAROCKS_VER: 2.3.0 cache: - c:\lua -> appveyor.yml - c:\external -> appveyor.yml install: - git submodule update --init for: - # For testing building from git matrix: only: - FROM_DEPS: true build_script: - msvcbuild.bat - luajit.exe tests\run.lua artifacts: - path: luv.dll - path: luajit.exe - # For testing LuaRocks matrix: except: - FROM_DEPS: true build_script: - call .ci\set_compiler_env.bat - call .ci\install.bat - luarocks make - luarocks show luv - ps: if("$(Get-Location)" -eq $(lua -e "print(require'luv'.cwd())")) { "LuaRocks test OK" } else { "LuaRocks test failed"; exit 1 } - lua tests\run.lua - luarocks remove luv # Test the alternate rockspec - mkdir build\lib - cp build.luarocks\deps\libuv\Release\uv_a.lib build\lib\uv.lib - cp -a deps\libuv\include build - ps: luarocks make rockspecs\$(ls rockspecs) LIBUV_DIR=build LUA_COMPAT53_INCDIR=deps/lua-compat-5.3/c-api CFLAGS="/nologo /MT /O2" - ps: if("$(Get-Location)" -eq $(lua -e "print(require'luv'.cwd())")) { "LuaRocks test OK" } else { "LuaRocks test failed"; exit 1 } - luarocks remove luv luv-1.36.0-0/cmake/000077500000000000000000000000001364617304100136315ustar00rootroot00000000000000luv-1.36.0-0/cmake/Modules/000077500000000000000000000000001364617304100152415ustar00rootroot00000000000000luv-1.36.0-0/cmake/Modules/FindLibuv.cmake000066400000000000000000000024441364617304100201310ustar00rootroot00000000000000#============================================================================= # Copyright 2016 The Luvit Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #============================================================================= # Locate libuv library # This module defines # LIBUV_FOUND, if false, do not try to link to libuv # LIBUV_LIBRARIES # LIBUV_INCLUDE_DIR, where to find uv.h FIND_PATH(LIBUV_INCLUDE_DIR NAMES uv.h) FIND_LIBRARY(LIBUV_LIBRARIES NAMES uv libuv) if(WIN32) list(APPEND LIBUV_LIBRARIES iphlpapi) list(APPEND LIBUV_LIBRARIES psapi) list(APPEND LIBUV_LIBRARIES userenv) list(APPEND LIBUV_LIBRARIES ws2_32) endif() INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUV DEFAULT_MSG LIBUV_LIBRARIES LIBUV_INCLUDE_DIR) luv-1.36.0-0/cmake/Modules/FindLuaJIT.cmake000066400000000000000000000057501364617304100201430ustar00rootroot00000000000000#============================================================================= # Copyright 2007-2009 Kitware, Inc. # Copyright 2013 Rolf Eike Beer # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # We use code from the CMake project to detect the Lua version. # Locate LuaJIT library # This module defines # LUAJIT_FOUND, if false, do not try to link to Lua JIT # LUAJIT_LIBRARIES # LUAJIT_INCLUDE_DIR, where to find lua.h # # Additionally it defines the Lua API/ABI version: # LUA_VERSION_STRING - the version of Lua found # LUA_VERSION_MAJOR - the major version of Lua # LUA_VERSION_MINOR - the minor version of Lua # LUA_VERSION_PATCH - the patch version of Lua FIND_PATH(LUAJIT_INCLUDE_DIR NAMES lua.h PATH_SUFFIXES luajit-2.0 luajit-2.1) FIND_LIBRARY(LUAJIT_LIBRARIES NAMES luajit-5.1 luajit) if (LUAJIT_INCLUDE_DIR AND EXISTS "${LUAJIT_INCLUDE_DIR}/lua.h") # At least 5.[012] have different ways to express the version # so all of them need to be tested. Lua 5.2 defines LUA_VERSION # and LUA_RELEASE as joined by the C preprocessor, so avoid those. file(STRINGS "${LUAJIT_INCLUDE_DIR}/lua.h" lua_version_strings REGEX "^#define[ \t]+LUA_(RELEASE[ \t]+\"Lua [0-9]|VERSION([ \t]+\"Lua [0-9]|_[MR])).*") string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MAJOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MAJOR ";${lua_version_strings};") if (LUA_VERSION_MAJOR MATCHES "^[0-9]+$") string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MINOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MINOR ";${lua_version_strings};") string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_RELEASE[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_PATCH ";${lua_version_strings};") set(LUA_VERSION_STRING "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}.${LUA_VERSION_PATCH}") else () string(REGEX REPLACE ".*;#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};") if (NOT LUA_VERSION_STRING MATCHES "^[0-9.]+$") string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};") endif () string(REGEX REPLACE "^([0-9]+)\\.[0-9.]*$" "\\1" LUA_VERSION_MAJOR "${LUA_VERSION_STRING}") string(REGEX REPLACE "^[0-9]+\\.([0-9]+)[0-9.]*$" "\\1" LUA_VERSION_MINOR "${LUA_VERSION_STRING}") string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]).*" "\\1" LUA_VERSION_PATCH "${LUA_VERSION_STRING}") endif () unset(lua_version_strings) endif() INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LUAJIT DEFAULT_MSG LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR) luv-1.36.0-0/deps/000077500000000000000000000000001364617304100135045ustar00rootroot00000000000000luv-1.36.0-0/deps/libuv/000077500000000000000000000000001364617304100146255ustar00rootroot00000000000000luv-1.36.0-0/deps/lua/000077500000000000000000000000001364617304100142655ustar00rootroot00000000000000luv-1.36.0-0/deps/lua-compat-5.3/000077500000000000000000000000001364617304100160515ustar00rootroot00000000000000luv-1.36.0-0/deps/lua.cmake000066400000000000000000000111721364617304100152710ustar00rootroot00000000000000# Modfied from luajit.cmake # Added LUA_ADD_EXECUTABLE Ryan Phillips # This CMakeLists.txt has been first taken from LuaDist # Copyright (C) 2007-2011 LuaDist. # Created by Peter Drahoš # Redistribution and use of this file is allowed according to the terms of the MIT license. # Debugged and (now seriously) modified by Ronan Collobert, for Torch7 #project(Lua53 C) SET(LUA_DIR ${CMAKE_CURRENT_LIST_DIR}/lua CACHE PATH "location of lua sources") SET(CMAKE_REQUIRED_INCLUDES ${LUA_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) OPTION(WITH_AMALG "Build eveything in one shot (needs memory)" ON) # Ugly warnings IF(MSVC) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) ENDIF() # Various includes INCLUDE(CheckLibraryExists) INCLUDE(CheckFunctionExists) INCLUDE(CheckCSourceCompiles) INCLUDE(CheckTypeSize) CHECK_TYPE_SIZE("void*" SIZEOF_VOID_P) IF(SIZEOF_VOID_P EQUAL 8) ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE) ENDIF() IF(NOT WIN32) FIND_LIBRARY(DL_LIBRARY "dl") IF(DL_LIBRARY) SET(CMAKE_REQUIRED_LIBRARIES ${DL_LIBRARY}) LIST(APPEND LIBS ${DL_LIBRARY}) ENDIF(DL_LIBRARY) CHECK_FUNCTION_EXISTS(dlopen LUA_USE_DLOPEN) IF(NOT LUA_USE_DLOPEN) MESSAGE(FATAL_ERROR "Cannot compile a useful lua. Function dlopen() seems not to be supported on your platform. Apparently you are not on a Windows platform as well. So lua has no way to deal with shared libraries!") ENDIF(NOT LUA_USE_DLOPEN) ENDIF(NOT WIN32) check_library_exists(m sin "" LUA_USE_LIBM) if ( LUA_USE_LIBM ) list ( APPEND LIBS m ) endif () ## SOURCES SET(SRC_LUALIB ${LUA_DIR}/lbaselib.c ${LUA_DIR}/lcorolib.c ${LUA_DIR}/ldblib.c ${LUA_DIR}/liolib.c ${LUA_DIR}/lmathlib.c ${LUA_DIR}/loadlib.c ${LUA_DIR}/loslib.c ${LUA_DIR}/lstrlib.c ${LUA_DIR}/ltablib.c ${LUA_DIR}/lutf8lib.c) SET(SRC_LUACORE ${LUA_DIR}/lauxlib.c ${LUA_DIR}/lapi.c ${LUA_DIR}/lcode.c ${LUA_DIR}/lctype.c ${LUA_DIR}/ldebug.c ${LUA_DIR}/ldo.c ${LUA_DIR}/ldump.c ${LUA_DIR}/lfunc.c ${LUA_DIR}/lgc.c ${LUA_DIR}/linit.c ${LUA_DIR}/llex.c ${LUA_DIR}/lmem.c ${LUA_DIR}/lobject.c ${LUA_DIR}/lopcodes.c ${LUA_DIR}/lparser.c ${LUA_DIR}/lstate.c ${LUA_DIR}/lstring.c ${LUA_DIR}/ltable.c ${LUA_DIR}/ltm.c ${LUA_DIR}/lundump.c ${LUA_DIR}/lvm.c ${LUA_DIR}/lzio.c ${SRC_LUALIB}) ## GENERATE IF(WITH_SHARED_LUA) IF(WITH_AMALG) add_library(lualib SHARED ${LUA_DIR}/../lua_one.c) ELSE() add_library(lualib SHARED ${SRC_LUACORE}) ENDIF() ELSE() IF(WITH_AMALG) add_library(lualib STATIC ${LUA_DIR}/../lua_one.c ) ELSE() add_library(lualib STATIC ${SRC_LUACORE} ) ENDIF() set_target_properties(lualib PROPERTIES PREFIX "lib" IMPORT_PREFIX "lib") ENDIF() target_link_libraries (lualib ${LIBS} ) set_target_properties (lualib PROPERTIES OUTPUT_NAME "lua53") add_executable(lua ${LUA_DIR}/lua.c) IF(WIN32) target_link_libraries(lua lualib) ELSE() target_link_libraries(lua lualib ${LIBS}) SET_TARGET_PROPERTIES(lua PROPERTIES ENABLE_EXPORTS ON) ENDIF(WIN32) MACRO(LUA_add_custom_commands luajit_target) SET(target_srcs "") FOREACH(file ${ARGN}) IF(${file} MATCHES ".*\\.lua$") if(NOT IS_ABSOLUTE ${file}) set(file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") endif() set(source_file ${file}) string(LENGTH ${CMAKE_SOURCE_DIR} _luajit_source_dir_length) string(LENGTH ${file} _luajit_file_length) math(EXPR _begin "${_luajit_source_dir_length} + 1") math(EXPR _stripped_file_length "${_luajit_file_length} - ${_luajit_source_dir_length} - 1") string(SUBSTRING ${file} ${_begin} ${_stripped_file_length} stripped_file) set(generated_file "${CMAKE_BINARY_DIR}/luacode_tmp/${stripped_file}_${luajit_target}_generated.c") add_custom_command( OUTPUT ${generated_file} MAIN_DEPENDENCY ${source_file} DEPENDS lua COMMAND lua ARGS "${LUA_DIR}/../luac.lua" ${source_file} ${generated_file} COMMENT "Building Lua ${source_file}: ${generated_file}" ) get_filename_component(basedir ${generated_file} PATH) file(MAKE_DIRECTORY ${basedir}) set(target_srcs ${target_srcs} ${generated_file}) set_source_files_properties( ${generated_file} properties generated true # to say that "it is OK that the obj-files do not exist before build time" ) ELSE() set(target_srcs ${target_srcs} ${file}) ENDIF(${file} MATCHES ".*\\.lua$") ENDFOREACH(file) ENDMACRO() MACRO(LUA_ADD_EXECUTABLE luajit_target) LUA_add_custom_commands(${luajit_target} ${ARGN}) add_executable(${luajit_target} ${target_srcs}) ENDMACRO(LUA_ADD_EXECUTABLE luajit_target) luv-1.36.0-0/deps/lua_one.c000066400000000000000000000034151364617304100152750ustar00rootroot00000000000000/* * one.c -- Lua core, libraries, and interpreter in a single file */ /* default is to build the full interpreter */ #ifndef MAKE_LIB #ifndef MAKE_LUAC #ifndef MAKE_LUA #define MAKE_LIB #endif #endif #endif /* choose suitable platform-specific features */ /* some of these may need extra libraries such as -ldl -lreadline -lncurses */ #if 0 #define LUA_USE_LINUX #define LUA_USE_MACOSX #define LUA_USE_POSIX #define LUA_ANSI #endif /* no need to change anything below this line ----------------------------- */ /* setup for luaconf.h */ #if HAVE_LPREFIX # include "lprefix.h" #endif #define LUA_CORE #define LUA_LIB #define ltable_c #define lvm_c #include "luaconf.h" /* do not export internal symbols */ #undef LUAI_FUNC #undef LUAI_DDEC #undef LUAI_DDEF #define LUAI_FUNC static #define LUAI_DDEC static #define LUAI_DDEF static /* core -- used by all */ #include "lapi.c" #include "lcode.c" #include "lctype.c" #include "ldebug.c" #include "ldo.c" #include "ldump.c" #include "lfunc.c" #include "lgc.c" #include "llex.c" #include "lmem.c" #include "lobject.c" #include "lopcodes.c" #include "lparser.c" #include "lstate.c" #include "lstring.c" #include "ltable.c" #include "ltm.c" #include "lundump.c" #include "lvm.c" #include "lzio.c" /* auxiliary library -- used by all */ #include "lauxlib.c" /* standard library -- not used by luac */ #ifndef MAKE_LUAC #include "lbaselib.c" #if LUA_VERSION_NUM == 502 # include "lbitlib.c" #endif #include "lcorolib.c" #include "ldblib.c" #include "liolib.c" #include "lmathlib.c" #include "loadlib.c" #include "loslib.c" #include "lstrlib.c" #include "ltablib.c" #if LUA_VERSION_NUM >= 503 # include "lutf8lib.c" #endif #include "linit.c" #endif /* lua */ #ifdef MAKE_LUA #include "lua.c" #endif /* luac */ #ifdef MAKE_LUAC #include "luac.c" #endif luv-1.36.0-0/deps/luac.lua000066400000000000000000000043501364617304100151350ustar00rootroot00000000000000--[[ Copyright 2014 The Luvit Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. s ]] local src, gen = ... local chunk = assert(loadfile(src, nil, '@'..src)) local bytecode = string.dump(chunk) local function basename(name) local base = name if base:match "[/\\]" then base = name:match("^.*[/\\](.*)$") end base = base:gsub("^%.", "_") if base:match "%." then base = base:match("^(.*)%."):gsub("%.", "_") end return base end local function escapefn(name) return '"'.. name:gsub('\\', '\\\\') :gsub('\n', '\\n') :gsub('\r', '\\r') :gsub('"', '\\"')..'"' end local function write_chunk(s) local t = { "{\n " }; local cc = 7 for i = 1, #s do local c = string.byte(s, i, i) local ss = (" 0x%X"):format(c) if cc + #ss > 77 then t[#t+1] = "\n " t[#t+1] = ss cc = 7 + #ss if i ~= #s then t[#t+1] = "," cc = cc + 1 end else t[#t+1] = ss cc = cc + #ss if i ~= #s then t[#t+1] = "," cc = cc + 1 end end end t[#t+1] = "\n }" return (table.concat(t)) end local function W(...) io.write(...) return W end io.output(gen) W [[ /* generated source for Lua codes */ #ifndef LUA_LIB # define LUA_LIB #endif #include #include LUALIB_API int luaopen_]](basename(src))[[(lua_State *L) { size_t len = ]](#bytecode)[[; const char chunk[] = ]](write_chunk(bytecode))[[; if (luaL_loadbuffer(L, chunk, len, ]](escapefn(src))[[) != 0) lua_error(L); lua_insert(L, 1); lua_call(L, lua_gettop(L)-1, LUA_MULTRET); return lua_gettop(L); } ]] io.close() luv-1.36.0-0/deps/luajit/000077500000000000000000000000001364617304100147745ustar00rootroot00000000000000luv-1.36.0-0/deps/luajit.cmake000066400000000000000000000254601364617304100160050ustar00rootroot00000000000000# Added LUA_ADD_EXECUTABLE Ryan Phillips # This CMakeLists.txt has been first taken from LuaDist # Copyright (C) 2007-2011 LuaDist. # Created by Peter Drahoš # Redistribution and use of this file is allowed according to the terms of the MIT license. # Debugged and (now seriously) modified by Ronan Collobert, for Torch7 #project(LuaJIT C ASM) SET(LUAJIT_DIR ${CMAKE_CURRENT_LIST_DIR}/luajit) SET(CMAKE_REQUIRED_INCLUDES ${LUAJIT_DIR} ${LUAJIT_DIR}/src ${CMAKE_CURRENT_BINARY_DIR} ) OPTION(WITH_AMALG "Build eveything in one shot (needs memory)" ON) # Ugly warnings IF(MSVC) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) ENDIF() # Various includes INCLUDE(CheckLibraryExists) INCLUDE(CheckFunctionExists) INCLUDE(CheckCSourceCompiles) INCLUDE(CheckTypeSize) # LuaJIT specific option(LUAJIT_DISABLE_FFI "Disable FFI." OFF) option(LUAJIT_ENABLE_LUA52COMPAT "Enable Lua 5.2 compatibility." ON) option(LUAJIT_DISABLE_JIT "Disable JIT." OFF) option(LUAJIT_CPU_SSE2 "Use SSE2 instead of x87 instructions." ON) option(LUAJIT_CPU_NOCMOV "Disable NOCMOV." OFF) option(LUAJIT_DISABLE_GC64 "Disable GC64" OFF) MARK_AS_ADVANCED(LUAJIT_DISABLE_FFI LUAJIT_ENABLE_LUA52COMPAT LUAJIT_DISABLE_GC64 LUAJIT_DISABLE_JIT LUAJIT_CPU_SSE2 LUAJIT_CPU_NOCMOV) IF(LUAJIT_DISABLE_FFI) ADD_DEFINITIONS(-DLUAJIT_DISABLE_FFI) ENDIF() IF(LUAJIT_ENABLE_LUA52COMPAT) ADD_DEFINITIONS(-DLUAJIT_ENABLE_LUA52COMPAT) ENDIF() IF(LUAJIT_DISABLE_GC64) ADD_DEFINITIONS(-DLUAJIT_DISABLE_GC64) ENDIF() IF(LUAJIT_DISABLE_JIT) ADD_DEFINITIONS(-DLUAJIT_DISABLE_JIT) ENDIF() IF(LUAJIT_CPU_SSE2) ADD_DEFINITIONS(-DLUAJIT_CPU_SSE2) ENDIF() IF(LUAJIT_CPU_NOCMOV) ADD_DEFINITIONS(-DLUAJIT_CPU_NOCMOV) ENDIF() ###### CHECK_TYPE_SIZE("void*" SIZEOF_VOID_P) IF(SIZEOF_VOID_P EQUAL 8) ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE) ENDIF() if ( WIN32 AND NOT CYGWIN ) set ( LJVM_MODE peobj ) elseif ( APPLE ) set ( CMAKE_EXE_LINKER_FLAGS "-pagezero_size 10000 -image_base 100000000 ${CMAKE_EXE_LINKER_FLAGS}" ) set ( LJVM_MODE machasm ) else () set ( LJVM_MODE elfasm ) endif () IF(NOT WIN32) FIND_LIBRARY(DL_LIBRARY "dl") IF(DL_LIBRARY) SET(CMAKE_REQUIRED_LIBRARIES ${DL_LIBRARY}) LIST(APPEND LIBS ${DL_LIBRARY}) ENDIF(DL_LIBRARY) CHECK_FUNCTION_EXISTS(dlopen LUA_USE_DLOPEN) IF(NOT LUA_USE_DLOPEN) MESSAGE(FATAL_ERROR "Cannot compile a useful lua. Function dlopen() seems not to be supported on your platform. Apparently you are not on a Windows platform as well. So lua has no way to deal with shared libraries!") ENDIF(NOT LUA_USE_DLOPEN) ENDIF(NOT WIN32) check_library_exists(m sin "" LUA_USE_LIBM) if ( LUA_USE_LIBM ) list ( APPEND LIBS m ) endif () if ( CMAKE_SYSTEM_NAME MATCHES "OpenBSD") list ( APPEND LIBS pthread c++abi ) endif () ## SOURCES MACRO(LJ_TEST_ARCH stuff) CHECK_C_SOURCE_COMPILES(" #undef ${stuff} #include \"lj_arch.h\" #if ${stuff} int main() { return 0; } #else #error \"not defined\" #endif " ${stuff}) ENDMACRO() MACRO(LJ_TEST_ARCH_VALUE stuff value) CHECK_C_SOURCE_COMPILES(" #undef ${stuff} #include \"lj_arch.h\" #if ${stuff} == ${value} int main() { return 0; } #else #error \"not defined\" #endif " ${stuff}_${value}) ENDMACRO() FOREACH(arch X64 X86 ARM ARM64 PPC PPCSPE MIPS) LJ_TEST_ARCH(LJ_TARGET_${arch}) if(LJ_TARGET_${arch}) STRING(TOLOWER ${arch} TARGET_LJARCH) MESSAGE(STATUS "LuaJIT Target: ${TARGET_LJARCH}") BREAK() ENDIF() ENDFOREACH() IF(NOT TARGET_LJARCH) MESSAGE(FATAL_ERROR "architecture not supported") ELSE() MESSAGE(STATUS "LuaJIT target ${TARGET_LJARCH}") ENDIF() FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/jit) FILE(GLOB jit_files ${LUAJIT_DIR}/src/jit/*.lua) FILE(COPY ${jit_files} DESTINATION ${CMAKE_BINARY_DIR}/jit) SET(DASM_ARCH ${TARGET_LJARCH}) SET(DASM_FLAGS) SET(TARGET_ARCH) LIST(APPEND TARGET_ARCH "LUAJIT_TARGET=LUAJIT_ARCH_${TARGET_LJARCH}") LJ_TEST_ARCH_VALUE(LJ_ARCH_BITS 64) IF(LJ_ARCH_BITS_64) SET(DASM_FLAGS ${DASM_FLAGS} -D P64) ENDIF() LJ_TEST_ARCH_VALUE(LJ_HASJIT 1) IF(LJ_HASJIT_1) SET(DASM_FLAGS ${DASM_FLAGS} -D JIT) ENDIF() LJ_TEST_ARCH_VALUE(LJ_HASFFI 1) IF(LJ_HASFFI_1) SET(DASM_FLAGS ${DASM_FLAGS} -D FFI) ENDIF() LJ_TEST_ARCH_VALUE(LJ_DUALNUM 1) IF(LJ_DUALNUM_1) SET(DASM_FLAGS ${DASM_FLAGS} -D DUALNUM) ENDIF() LJ_TEST_ARCH_VALUE(LJ_ARCH_HASFPU 1) IF(LJ_ARCH_HASFPU_1) SET(DASM_FLAGS ${DASM_FLAGS} -D FPU) LIST(APPEND TARGET_ARCH "LJ_ARCH_HASFPU=1") ELSE() LIST(APPEND TARGET_ARCH "LJ_ARCH_HASFPU=0") ENDIF() LJ_TEST_ARCH_VALUE(LJ_ABI_SOFTFP 1) IF(NOT LJ_ABI_SOFTFP_1) SET(DASM_FLAGS ${DASM_FLAGS} -D HFABI) LIST(APPEND TARGET_ARCH "LJ_ABI_SOFTFP=0") ELSE() LIST(APPEND TARGET_ARCH "LJ_ABI_SOFTFP=1") ENDIF() IF(WIN32) SET(DASM_FLAGS ${DASM_FLAGS} -LN -D WIN) ENDIF() IF(TARGET_LJARCH STREQUAL "x86") LJ_TEST_ARCH_VALUE(__SSE2__ 1) IF(__SSE2__1) SET(DASM_FLAGS ${DASM_FLAGS} -D SSE) ENDIF() ENDIF() IF(TARGET_LJARCH STREQUAL "ppc") LJ_TEST_ARCH_VALUE(LJ_ARCH_SQRT 1) IF(NOT LJ_ARCH_SQRT_1) SET(DASM_FLAGS ${DASM_FLAGS} -D SQRT) ENDIF() LJ_TEST_ARCH_VALUE(LJ_ARCH_PPC64 1) IF(NOT LJ_ARCH_PPC64_1) SET(DASM_FLAGS ${DASM_FLAGS} -D GPR64) ENDIF() ENDIF() add_executable(minilua ${LUAJIT_DIR}/src/host/minilua.c) SET_TARGET_PROPERTIES(minilua PROPERTIES COMPILE_DEFINITIONS "${TARGET_ARCH}") CHECK_LIBRARY_EXISTS(m sin "" MINILUA_USE_LIBM) if(MINILUA_USE_LIBM) TARGET_LINK_LIBRARIES(minilua m) endif() add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/buildvm_arch.h COMMAND minilua ${LUAJIT_DIR}/dynasm/dynasm.lua ${DASM_FLAGS} -o ${CMAKE_CURRENT_BINARY_DIR}/buildvm_arch.h ${LUAJIT_DIR}/src/vm_${DASM_ARCH}.dasc DEPENDS ${LUAJIT_DIR}/dynasm/dynasm.lua minilua ) ## Source Lists SET(SRC_LJLIB ${LUAJIT_DIR}/src/lib_base.c ${LUAJIT_DIR}/src/lib_math.c ${LUAJIT_DIR}/src/lib_bit.c ${LUAJIT_DIR}/src/lib_string.c ${LUAJIT_DIR}/src/lib_table.c ${LUAJIT_DIR}/src/lib_io.c ${LUAJIT_DIR}/src/lib_os.c ${LUAJIT_DIR}/src/lib_package.c ${LUAJIT_DIR}/src/lib_debug.c ${LUAJIT_DIR}/src/lib_jit.c ${LUAJIT_DIR}/src/lib_ffi.c ) SET(SRC_LIBAUX ${LUAJIT_DIR}/src/lib_aux.c ${LUAJIT_DIR}/src/lib_init.c ) file (GLOB_RECURSE SRC_LJCORE "${LUAJIT_DIR}/src/lj_*.c") list (APPEND SRC_LJCORE ${SRC_LJLIB} ${SRC_LIBAUX}) file (GLOB_RECURSE SRC_BUILDVM "${LUAJIT_DIR}/src/host/buildvm*.c") list (APPEND SRC_BUILDVM ${CMAKE_CURRENT_BINARY_DIR}/buildvm_arch.h) ## GENERATE ADD_EXECUTABLE(buildvm ${SRC_BUILDVM}) SET_TARGET_PROPERTIES(buildvm PROPERTIES COMPILE_DEFINITIONS "${TARGET_ARCH}") macro(add_buildvm_target _target _mode) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_target} COMMAND buildvm ARGS -m ${_mode} -o ${CMAKE_CURRENT_BINARY_DIR}/${_target} ${ARGN} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS buildvm ${ARGN} ) endmacro(add_buildvm_target) if (WIN32) add_buildvm_target ( lj_vm.obj peobj ) set (LJ_VM_SRC ${CMAKE_CURRENT_BINARY_DIR}/lj_vm.obj) else () add_buildvm_target ( lj_vm.S ${LJVM_MODE} ) set (LJ_VM_SRC ${CMAKE_CURRENT_BINARY_DIR}/lj_vm.S) endif () add_buildvm_target ( lj_ffdef.h ffdef ${SRC_LJLIB} ) add_buildvm_target ( lj_bcdef.h bcdef ${SRC_LJLIB} ) add_buildvm_target ( lj_folddef.h folddef ${LUAJIT_DIR}/src/lj_opt_fold.c ) add_buildvm_target ( lj_recdef.h recdef ${SRC_LJLIB} ) add_buildvm_target ( lj_libdef.h libdef ${SRC_LJLIB} ) add_buildvm_target ( vmdef.lua vmdef ${SRC_LJLIB} ) SET(DEPS ${LJ_VM_SRC} ${CMAKE_CURRENT_BINARY_DIR}/lj_ffdef.h ${CMAKE_CURRENT_BINARY_DIR}/lj_bcdef.h ${CMAKE_CURRENT_BINARY_DIR}/lj_libdef.h ${CMAKE_CURRENT_BINARY_DIR}/lj_recdef.h ${CMAKE_CURRENT_BINARY_DIR}/lj_folddef.h ${CMAKE_CURRENT_BINARY_DIR}/vmdef.lua ) ## COMPILE include_directories( ${LUAJIT_DIR}/dynasm ${LUAJIT_DIR}/src ${CMAKE_CURRENT_BINARY_DIR} ) IF(WITH_SHARED_LUA) IF(WITH_AMALG) add_library(luajit-5.1 SHARED ${LUAJIT_DIR}/src/ljamalg.c ${DEPS} ) ELSE() add_library(luajit-5.1 SHARED ${SRC_LJCORE} ${DEPS} ) ENDIF() SET_TARGET_PROPERTIES(luajit-5.1 PROPERTIES OUTPUT_NAME "lua51") ELSE() IF(WITH_AMALG) add_library(luajit-5.1 STATIC ${LUAJIT_DIR}/src/ljamalg.c ${DEPS} ) ELSE() add_library(luajit-5.1 STATIC ${SRC_LJCORE} ${DEPS} ) ENDIF() SET_TARGET_PROPERTIES(luajit-5.1 PROPERTIES PREFIX "lib" IMPORT_PREFIX "lib" OUTPUT_NAME "luajit") ENDIF() target_link_libraries (luajit-5.1 ${LIBS} ) IF(WIN32) add_executable(luajit ${LUAJIT_DIR}/src/luajit.c) target_link_libraries(luajit luajit-5.1) ELSE() IF(WITH_AMALG) add_executable(luajit ${LUAJIT_DIR}/src/luajit.c ${LUAJIT_DIR}/src/ljamalg.c ${DEPS}) # When using WITH_AMALG during a parallel build, its possible to run into # false-positive "error: 'fold_hash' undeclared" compile errors due to a weird interaction # when building two ljamalg.c at the same time. # # This adds a fake dependency from one to the other, forcing the build process to # compile them sequentially rather than parallel. # # See https://github.com/torch/luajit-rocks/issues/39 add_dependencies(luajit luajit-5.1) ELSE() add_executable(luajit ${LUAJIT_DIR}/src/luajit.c ${SRC_LJCORE} ${DEPS}) ENDIF() target_link_libraries(luajit ${LIBS}) SET_TARGET_PROPERTIES(luajit PROPERTIES ENABLE_EXPORTS ON) ENDIF() MACRO(LUAJIT_add_custom_commands luajit_target) SET(target_srcs "") FOREACH(file ${ARGN}) IF(${file} MATCHES ".*\\.lua$") if(NOT IS_ABSOLUTE ${file}) set(file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") endif() set(source_file ${file}) string(LENGTH ${CMAKE_SOURCE_DIR} _luajit_source_dir_length) string(LENGTH ${file} _luajit_file_length) math(EXPR _begin "${_luajit_source_dir_length} + 1") math(EXPR _stripped_file_length "${_luajit_file_length} - ${_luajit_source_dir_length} - 1") string(SUBSTRING ${file} ${_begin} ${_stripped_file_length} stripped_file) set(generated_file "${CMAKE_BINARY_DIR}/jitted_tmp/${stripped_file}_${luajit_target}_generated${CMAKE_C_OUTPUT_EXTENSION}") add_custom_command( OUTPUT ${generated_file} MAIN_DEPENDENCY ${source_file} DEPENDS luajit COMMAND luajit ARGS -bg ${source_file} ${generated_file} COMMENT "Building Luajitted ${source_file}: ${generated_file}" ) get_filename_component(basedir ${generated_file} PATH) file(MAKE_DIRECTORY ${basedir}) set(target_srcs ${target_srcs} ${generated_file}) set_source_files_properties( ${generated_file} properties external_object true # this is an object file generated true # to say that "it is OK that the obj-files do not exist before build time" ) ELSE() set(target_srcs ${target_srcs} ${file}) ENDIF(${file} MATCHES ".*\\.lua$") ENDFOREACH(file) ENDMACRO() MACRO(LUA_ADD_EXECUTABLE luajit_target) LUAJIT_add_custom_commands(${luajit_target} ${ARGN}) add_executable(${luajit_target} ${target_srcs}) ENDMACRO(LUA_ADD_EXECUTABLE luajit_target) luv-1.36.0-0/docs.md000066400000000000000000002630121364617304100140270ustar00rootroot00000000000000# LibUV in Lua The [luv][] project provides access to the multi-platform support library [libuv][] in Lua code. It was primarily developed for the [luvit][] project as the built-in `uv` module, but can be used in other Lua environments. More information about the core libuv library can be found at the original [libuv documentation page][]. ### TCP Echo Server Example Here is a small example showing a TCP echo server: ```lua local uv = require("luv") -- "luv" when stand-alone, "uv" in luvi apps local server = uv.new_tcp() server:bind("127.0.0.1", 1337) server:listen(128, function (err) assert(not err, err) local client = uv.new_tcp() server:accept(client) client:read_start(function (err, chunk) assert(not err, err) if chunk then client:write(chunk) else client:shutdown() client:close() end end) end) print("TCP server listening at 127.0.0.1 port 1337") uv.run() -- an explicit run call is necessary outside of luvit ``` ### Module Layout The luv library contains a single Lua module referred to hereafter as `uv` for simplicity. This module consists mostly of functions with names corresponding to their original libuv versions. For example, the libuv function `uv_tcp_bind` has a luv version at `uv.tcp_bind`. Currently, only one non-function field exists: `uv.constants`, which is a table. ### Functions vs Methods In addition to having simple functions, luv provides an optional method-style API. For example, `uv.tcp_bind(server, host, port)` can alternatively be called as `server:bind(host, port)`. Note that the first argument `server` becomes the object and `tcp_` is removed from the function name. Method forms are documented below where they exist. ### Synchronous vs Asynchronous Functions Functions that accept a callback are asynchronous. These functions may immediately return results to the caller to indicate their initial status, but their final execution is deferred until at least the next libuv loop iteration. After completion, their callbacks are executed with any results passed to it. Functions that do not accept a callback are synchronous. These functions immediately return their results to the caller. Some (generally FS and DNS) functions can behave either synchronously or asynchronously. If a callback is provided to these functions, they behave asynchronously; if no callback is provided, they behave synchronously. ### Pseudo-Types Some unique types are defined. These are not actual types in Lua, but they are used here to facilitate documenting consistent behavior: - `fail`: an assertable `nil, string, string` tuple (see [Error handling][]) - `callable`: a `function`; or a `table` or `userdata` with a `__call` metamethod - `buffer`: a `string` or a sequential `table` of `string`s - `threadargs`: variable arguments (`...`) of type `nil`, `boolean`, `number`, `string`, or `userdata` ## Contents This documentation is mostly a retelling of the [libuv API documentation][] within the context of luv's Lua API. Low-level implementation details and unexposed C functions and types are not documented here except for when they are relevant to behavior seen in the Lua module. - [Error handling][] - [Version checking][] - [`uv_loop_t`][] — Event loop - [`uv_req_t`][] — Base request - [`uv_handle_t`][] — Base handle - [`uv_timer_t`][] — Timer handle - [`uv_prepare_t`][] — Prepare handle - [`uv_check_t`][] — Check handle - [`uv_idle_t`][] — Idle handle - [`uv_async_t`][] — Async handle - [`uv_poll_t`][] — Poll handle - [`uv_signal_t`][] — Signal handle - [`uv_process_t`][] — Process handle - [`uv_stream_t`][] — Stream handle - [`uv_tcp_t`][] — TCP handle - [`uv_pipe_t`][] — Pipe handle - [`uv_tty_t`][] — TTY handle - [`uv_udp_t`][] — UDP handle - [`uv_fs_event_t`][] — FS Event handle - [`uv_fs_poll_t`][] — FS Poll handle - [File system operations][] - [Thread pool work scheduling][] - [DNS utility functions][] - [Threading and synchronization utilities][] - [Miscellaneous utilities][] ## Error Handling [Error handling]: #error-handling In libuv, errors are negative numbered constants; however, these errors and the functions used to handle them are not exposed to luv users. Instead, if an internal error is encountered, the luv function will return to the caller an assertable `nil, err, name` tuple. - `nil` idiomatically indicates failure - `err` is a string with the format `{name}: {message}` - `{name}` is the error name provided internally by `uv_err_name` - `{message}` is a human-readable message provided internally by `uv_strerror` - `name` is the same string used to construct `err` This tuple is referred to below as the `fail` pseudo-type. When a function is called successfully, it will return either a value that is relevant to the operation of the function, or the integer `0` to indicate success, or sometimes nothing at all. These cases are documented below. ## Version Checking [Version checking]: #version-checking ### `uv.version()` Returns the libuv version packed into a single integer. 8 bits are used for each component, with the patch number stored in the 8 least significant bits. For example, this would be 0x010203 in libuv 1.2.3. **Returns:** `integer` ### `uv.version_string()` Returns the libuv version number as a string. For example, this would be "1.2.3" in libuv 1.2.3. For non-release versions, the version suffix is included. **Returns:** `string` ## `uv_loop_t` — Event loop [`uv_loop_t`]: #uv_loop_t--event-loop The event loop is the central part of libuv's functionality. It takes care of polling for I/O and scheduling callbacks to be run based on different sources of events. In luv, there is an implicit uv loop for every Lua state that loads the library. You can use this library in an multi-threaded environment as long as each thread has it's own Lua state with its corresponding own uv loop. This loop is not directly exposed to users in the Lua module. ### `uv.loop_close()` Closes all internal loop resources. In normal execution, the loop will automatically be closed when it is garbage collected by Lua, so it is not necessary to explicitly call `loop_close()`. Call this function only after the loop has finished executing and all open handles and requests have been closed, or it will return `EBUSY`. **Returns:** `0` or `fail` ### `uv.run([mode])` **Parameters:** - `mode`: `string` or `nil` (default: `"default"`) This function runs the event loop. It will act differently depending on the specified mode: - `"default"`: Runs the event loop until there are no more active and referenced handles or requests. Returns `true` if `uv.stop()` was called and there are still active handles or requests. Returns `false` in all other cases. - `"once"`: Poll for I/O once. Note that this function blocks if there are no pending callbacks. Returns `false` when done (no active handles or requests left), or `true` if more callbacks are expected (meaning you should run the event loop again sometime in the future). - `"nowait"`: Poll for I/O once but don't block if there are no pending callbacks. Returns `false` if done (no active handles or requests left), or `true` if more callbacks are expected (meaning you should run the event loop again sometime in the future). **Returns:** `boolean` or `fail` **Note:** Luvit will implicitly call `uv.run()` after loading user code, but if you use the luv bindings directly, you need to call this after registering your initial set of event callbacks to start the event loop. ### `uv.loop_alive()` Returns `true` if there are referenced active handles, active requests, or closing handles in the loop; otherwise, `false`. **Returns:** `boolean` or `fail` ### `uv.stop()` Stop the event loop, causing `uv.run()` to end as soon as possible. This will happen not sooner than the next loop iteration. If this function was called before blocking for I/O, the loop won't block for I/O on this iteration. **Returns:** Nothing. ### `uv.backend_fd()` Get backend file descriptor. Only kqueue, epoll, and event ports are supported. This can be used in conjunction with `uv.run("nowait")` to poll in one thread and run the event loop's callbacks in another **Returns:** `integer` or `nil` **Note**: Embedding a kqueue fd in another kqueue pollset doesn't work on all platforms. It's not an error to add the fd but it never generates events. ### `uv.backend_timeout()` Get the poll timeout. The return value is in milliseconds, or -1 for no timeout. **Returns:** `integer` ### `uv.now()` Returns the current timestamp in milliseconds. The timestamp is cached at the start of the event loop tick, see `uv.update_time()` for details and rationale. The timestamp increases monotonically from some arbitrary point in time. Don't make assumptions about the starting point, you will only get disappointed. **Returns:** `integer` **Note**: Use `uv.hrtime()` if you need sub-millisecond granularity. ### `uv.update_time()` Update the event loop's concept of "now". Libuv caches the current time at the start of the event loop tick in order to reduce the number of time-related system calls. You won't normally need to call this function unless you have callbacks that block the event loop for longer periods of time, where "longer" is somewhat subjective but probably on the order of a millisecond or more. **Returns:** Nothing. ### `uv.walk(callback)` **Parameters:** - `callback`: `callable` - `handle`: `userdata` for sub-type of `uv_handle_t` Walk the list of handles: `callback` will be executed with each handle. **Returns:** Nothing. ```lua -- Example usage of uv.walk to close all handles that aren't already closing. uv.walk(function (handle) if not handle:is_closing() then handle:close() end end) ``` ## `uv_req_t` — Base request [`uv_req_t`]: #uv_req_t--request-handle `uv_req_t` is the base type for all libuv request types. ### `uv.cancel(req)` **Parameters:** - `req`: `userdata` for sub-type of `uv_req_t` Cancel a pending request. Fails if the request is executing or has finished executing. Only cancellation of `uv_fs_t`, `uv_getaddrinfo_t`, `uv_getnameinfo_t` and `uv_work_t` requests is currently supported. **Returns:** `0` or `fail` ## `uv_handle_t` — Base handle [`uv_handle_t`]: #uv_handle_t--base-handle `uv_handle_t` is the base type for all libuv handle types. All API functions defined here work with any handle type. ### `uv.is_active(handle)` > method form `handle:is_active()` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` Returns `true` if the handle is active, `false` if it's inactive. What "active” means depends on the type of handle: - A [`uv_async_t`][] handle is always active and cannot be deactivated, except by closing it with `uv.close()`. - A [`uv_pipe_t`][], [`uv_tcp_t`][], [`uv_udp_t`][], etc. handle - basically any handle that deals with I/O - is active when it is doing something that involves I/O, like reading, writing, connecting, accepting new connections, etc. - A [`uv_check_t`][], [`uv_idle_t`][], [`uv_timer_t`][], etc. handle is active when it has been started with a call to `uv.check_start()`, `uv.idle_start()`, `uv.timer_start()` etc. until it has been stopped with a call to its respective stop function. **Returns:** `boolean` or `fail` ### `uv.is_closing(handle)` > method form `handle:is_closing()` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` Returns `true` if the handle is closing or closed, `false` otherwise. **Returns:** `boolean` or `fail` **Note**: This function should only be used between the initialization of the handle and the arrival of the close callback. ### `uv.close(handle, [callback])` > method form `handle:close([callback])` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` - `callback`: `callable` or `nil` Request handle to be closed. `callback` will be called asynchronously after this call. This MUST be called on each handle before memory is released. Handles that wrap file descriptors are closed immediately but `callback` will still be deferred to the next iteration of the event loop. It gives you a chance to free up any resources associated with the handle. In-progress requests, like `uv_connect_t` or `uv_write_t`, are cancelled and have their callbacks called asynchronously with `ECANCELED`. **Returns:** Nothing. ### `uv.ref(handle)` > method form `handle:ref()` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` Reference the given handle. References are idempotent, that is, if a handle is already referenced calling this function again will have no effect. **Returns:** Nothing. See [Reference counting][]. ### `uv.unref(handle)` > method form `handle:unref()` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` Un-reference the given handle. References are idempotent, that is, if a handle is not referenced calling this function again will have no effect. **Returns:** Nothing. See [Reference counting][]. ### `uv.has_ref(handle)` > method form `handle:has_ref()` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` Returns `true` if the handle referenced, `false` if not. **Returns:** `boolean` or `fail` See [Reference counting][]. ### `uv.send_buffer_size(handle, [size])` > method form `handle:send_buffer_size([size])` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` - `size`: `integer` or `nil` (default: `0`) Gets or sets the size of the send buffer that the operating system uses for the socket. If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP handles on Windows. **Returns:** - `integer` or `fail` (if `size` is `nil` or `0`) - `0` or `fail` (if `size` is not `nil` and not `0`) **Note**: Linux will set double the size and return double the size of the original set value. ### `uv.recv_buffer_size(handle, [size])` > method form `handle:recv_buffer_size([size])` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` - `size`: `integer` or `nil` (default: `0`) Gets or sets the size of the receive buffer that the operating system uses for the socket. If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP handles on Windows. **Returns:** - `integer` or `fail` (if `size` is `nil` or `0`) - `0` or `fail` (if `size` is not `nil` and not `0`) **Note**: Linux will set double the size and return double the size of the original set value. ### `uv.fileno(handle)` > method form `handle:fileno()` **Parameters:** - `handle`: `userdata` for sub-type of `uv_handle_t` Gets the platform dependent file descriptor equivalent. The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing any other handle type will fail with `EINVAL`. If a handle doesn't have an attached file descriptor yet or the handle itself has been closed, this function will return `EBADF`. **Returns:** `integer` or `fail` **Warning**: Be very careful when using this function. libuv assumes it's in control of the file descriptor so any change to it may lead to malfunction. ## Reference counting [reference counting]: #reference-counting The libuv event loop (if run in the default mode) will run until there are no active and referenced handles left. The user can force the loop to exit early by unreferencing handles which are active, for example by calling `uv.unref()` after calling `uv.timer_start()`. A handle can be referenced or unreferenced, the refcounting scheme doesn't use a counter, so both operations are idempotent. All handles are referenced when active by default, see `uv.is_active()` for a more detailed explanation on what being active involves. ## `uv_timer_t` — Timer handle [`uv_timer_t`]: #uv_timer_t--timer-handle > [`uv_handle_t`][] functions also apply. Timer handles are used to schedule callbacks to be called in the future. ### `uv.new_timer()` Creates and initializes a new `uv_timer_t`. Returns the Lua userdata wrapping it. **Returns:** `uv_timer_t userdata` or `fail` ```lua -- Creating a simple setTimeout wrapper local function setTimeout(timeout, callback) local timer = uv.new_timer() timer:start(timeout, 0, function () timer:stop() timer:close() callback() end) return timer end -- Creating a simple setInterval wrapper local function setInterval(interval, callback) local timer = uv.new_timer() timer:start(interval, interval, function () callback() end) return timer end -- And clearInterval local function clearInterval(timer) timer:stop() timer:close() end ``` ### `uv.timer_start(timer, timeout, repeat, callback)` > method form `timer:start(timeout, repeat, callback)` **Parameters:** - `timer`: `uv_timer_t userdata` - `timeout`: `integer` - `repeat`: `integer` - `callback`: `callable` Start the timer. `timeout` and `repeat` are in milliseconds. If `timeout` is zero, the callback fires on the next event loop iteration. If `repeat` is non-zero, the callback fires first after `timeout` milliseconds and then repeatedly after `repeat` milliseconds. **Returns:** `0` or `fail` ### `uv.timer_stop(timer)` > method form `timer:stop()` **Parameters:** - `timer`: `uv_timer_t userdata` Stop the timer, the callback will not be called anymore. **Returns:** `0` or `fail` ### `uv.timer_again(timer)` > method form `timer:again()` **Parameters:** - `timer`: `uv_timer_t userdata` Stop the timer, and if it is repeating restart it using the repeat value as the timeout. If the timer has never been started before it raises `EINVAL`. **Returns:** `0` or `fail` ### `uv.timer_set_repeat(timer, repeat)` > method form `timer:set_repeat(repeat)` **Parameters:** - `timer`: `uv_timer_t userdata` - `repeat`: `integer` Set the repeat interval value in milliseconds. The timer will be scheduled to run on the given interval, regardless of the callback execution duration, and will follow normal timer semantics in the case of a time-slice overrun. For example, if a 50 ms repeating timer first runs for 17 ms, it will be scheduled to run again 33 ms later. If other tasks consume more than the 33 ms following the first timer callback, then the callback will run as soon as possible. **Returns:** Nothing. ### `uv.timer_get_repeat(timer)` > method form `timer:get_repeat()` **Parameters:** - `timer`: `uv_timer_t userdata` Get the timer repeat value. **Returns:** `integer` ## `uv_prepare_t` — Prepare handle [`uv_prepare_t`]: #uv_prepare_t--prepare-handle > [`uv_handle_t`][] functions also apply. Prepare handles will run the given callback once per loop iteration, right before polling for I/O. ```lua local prepare = uv.new_prepare() prepare:start(function() print("Before I/O polling") end) ``` ### `uv.new_prepare()` Creates and initializes a new `uv_prepare_t`. Returns the Lua userdata wrapping it. **Returns:** `uv_prepare_t userdata` or `fail` ### `uv.prepare_start(prepare, callback)` > method form `prepare:start(callback)` **Parameters:** - `prepare`: `uv_prepare_t userdata` - `callback`: `callable` Start the handle with the given callback. **Returns:** `0` or `fail` ### `uv.prepare_stop(prepare)` > method form `prepare:stop()` **Parameters:** - `prepare`: `uv_prepare_t userdata` Stop the handle, the callback will no longer be called. **Returns:** `0` or `fail` ## `uv_check_t` — Check handle [`uv_check_t`]: #uv_check_t--check-handle > [`uv_handle_t`][] functions also apply. Check handles will run the given callback once per loop iteration, right after polling for I/O. ```lua local check = uv.new_check() check:start(function() print("After I/O polling") end) ``` ### `uv.new_check()` Creates and initializes a new `uv_check_t`. Returns the Lua userdata wrapping it. **Returns:** `uv_check_t userdata` or `fail` ### `uv.check_start(check, callback)` > method form `check:start(callback)` **Parameters:** - `check`: `uv_check_t userdata` - `callback`: `callable` Start the handle with the given callback. **Returns:** `0` or `fail` ### `uv.check_stop(check)` > method form `check:stop()` **Parameters:** - `check`: `uv_check_t userdata` Stop the handle, the callback will no longer be called. **Returns:** `0` or `fail` ## `uv_idle_t` — Idle handle [`uv_idle_t`]: #uv_idle_t--idle-handle > [`uv_handle_t`][] functions also apply. Idle handles will run the given callback once per loop iteration, right before the [`uv_prepare_t`][] handles. **Note**: The notable difference with prepare handles is that when there are active idle handles, the loop will perform a zero timeout poll instead of blocking for I/O. **Warning**: Despite the name, idle handles will get their callbacks called on every loop iteration, not when the loop is actually "idle". ```lua local idle = uv.new_idle() idle:start(function() print("Before I/O polling, no blocking") end) ``` ### `uv.new_idle()` Creates and initializes a new `uv_idle_t`. Returns the Lua userdata wrapping it. **Returns:** `uv_idle_t userdata` or `fail` ### `uv.idle_start(idle, callback)` > method form `idle:start(callback)` **Parameters:** - `idle`: `uv_idle_t userdata` - `callback`: `callable` Start the handle with the given callback. **Returns:** `0` or `fail` ### `uv.idle_stop(check)` > method form `idle:stop()` **Parameters:** - `idle`: `uv_idle_t userdata` Stop the handle, the callback will no longer be called. **Returns:** `0` or `fail` ## `uv_async_t` — Async handle [`uv_async_t`]: #uv_async_t--async-handle > [`uv_handle_t`][] functions also apply. Async handles allow the user to "wakeup" the event loop and get a callback called from another thread. ```lua local async async = uv.new_async(function() print("async operation ran") async:close() end) async:send() ``` ### `uv.new_async([callback])` **Parameters:** - `callback`: `callable` or `nil` - `...`: `threadargs` passed to/from `uv.async_send(async, ...)` Creates and initializes a new `uv_async_t`. Returns the Lua userdata wrapping it. A `nil` callback is allowed. **Returns:** `uv_async_t userdata` or `fail` **Note**: Unlike other handle initialization functions, this immediately starts the handle. ### `uv.async_send(async, ...)` > method form `async:send(...)` **Parameters:** - `async`: `uv_async_t userdata` - `...`: `threadargs` Wakeup the event loop and call the async handle's callback. **Returns:** `0` or `fail` **Note**: It's safe to call this function from any thread. The callback will be called on the loop thread. **Warning**: libuv will coalesce calls to `uv.async_send(async)`, that is, not every call to it will yield an execution of the callback. For example: if `uv.async_send()` is called 5 times in a row before the callback is called, the callback will only be called once. If `uv.async_send()` is called again after the callback was called, it will be called again. ## `uv_poll_t` — Poll handle [`uv_poll_t`]: #uv_poll_t--poll-handle > [`uv_handle_t`][] functions also apply. Poll handles are used to watch file descriptors for readability and writability, similar to the purpose of [poll(2)](http://linux.die.net/man/2/poll). The purpose of poll handles is to enable integrating external libraries that rely on the event loop to signal it about the socket status changes, like c-ares or libssh2. Using `uv_poll_t` for any other purpose is not recommended; `uv_tcp_t`, `uv_udp_t`, etc. provide an implementation that is faster and more scalable than what can be achieved with `uv_poll_t`, especially on Windows. It is possible that poll handles occasionally signal that a file descriptor is readable or writable even when it isn't. The user should therefore always be prepared to handle EAGAIN or equivalent when it attempts to read from or write to the fd. It is not okay to have multiple active poll handles for the same socket, this can cause libuv to busyloop or otherwise malfunction. The user should not close a file descriptor while it is being polled by an active poll handle. This can cause the handle to report an error, but it might also start polling another socket. However the fd can be safely closed immediately after a call to `uv.poll_stop()` or `uv.close()`. **Note**: On windows only sockets can be polled with poll handles. On Unix any file descriptor that would be accepted by poll(2) can be used. ### `uv.new_poll(fd)` **Parameters:** - `fd`: `integer` Initialize the handle using a file descriptor. The file descriptor is set to non-blocking mode. **Returns:** `uv_poll_t userdata` or `fail` ### `uv.new_socket_poll(fd)` **Parameters:** - `fd`: `integer` Initialize the handle using a socket descriptor. On Unix this is identical to `uv.new_poll()`. On windows it takes a SOCKET handle. The socket is set to non-blocking mode. **Returns:** `uv_poll_t userdata` or `fail` ### `uv.poll_start(poll, events, callback)` > method form `poll:start(events, callback)` **Parameters:** - `poll`: `uv_poll_t userdata` - `events`: `string` or `nil` (default: `"rw"`) - `callback`: `callable` - `err`: `nil` or `string` - `events`: `string` or `nil` Starts polling the file descriptor. `events` are: `"r"`, `"w"`, `"rw"`, `"d"`, `"rd"`, `"wd"`, `"rwd"`, `"p"`, `"rp"`, `"wp"`, `"rwp"`, `"dp"`, `"rdp"`, `"wdp"`, or `"rwdp"` where `r` is `READABLE`, `w` is `WRITABLE`, `d` is `DISCONNECT`, and `p` is `PRIORITIZED`. As soon as an event is detected the callback will be called with status set to 0, and the detected events set on the events field. The user should not close the socket while the handle is active. If the user does that anyway, the callback may be called reporting an error status, but this is not guaranteed. **Returns:** `0` or `fail` **Note** Calling `uv.poll_start()` on a handle that is already active is fine. Doing so will update the events mask that is being watched for. ### `uv.poll_stop(poll)` > method form `poll:stop()` **Parameters:** - `poll`: `uv_poll_t userdata` Stop polling the file descriptor, the callback will no longer be called. **Returns:** `0` or `fail` ## `uv_signal_t` — Signal handle [`uv_signal_t`]: #uv_signal_t--signal-handle > [`uv_handle_t`][] functions also apply. Signal handles implement Unix style signal handling on a per-event loop bases. **Windows Notes:** Reception of some signals is emulated on Windows: - SIGINT is normally delivered when the user presses CTRL+C. However, like on Unix, it is not generated when terminal raw mode is enabled. - SIGBREAK is delivered when the user pressed CTRL + BREAK. - SIGHUP is generated when the user closes the console window. On SIGHUP the program is given approximately 10 seconds to perform cleanup. After that Windows will unconditionally terminate it. - SIGWINCH is raised whenever libuv detects that the console has been resized. SIGWINCH is emulated by libuv when the program uses a uv_tty_t handle to write to the console. SIGWINCH may not always be delivered in a timely manner; libuv will only detect size changes when the cursor is being moved. When a readable [`uv_tty_t`][] handle is used in raw mode, resizing the console buffer will also trigger a SIGWINCH signal. - Watchers for other signals can be successfully created, but these signals are never received. These signals are: SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTERM and SIGKILL. - Calls to raise() or abort() to programmatically raise a signal are not detected by libuv; these will not trigger a signal watcher. **Unix Notes:** - SIGKILL and SIGSTOP are impossible to catch. - Handling SIGBUS, SIGFPE, SIGILL or SIGSEGV via libuv results into undefined behavior. - SIGABRT will not be caught by libuv if generated by abort(), e.g. through assert(). - On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads library to manage threads. Installing watchers for those signals will lead to unpredictable behavior and is strongly discouraged. Future versions of libuv may simply reject them. ```lua -- Create a new signal handler local signal = uv.new_signal() -- Define a handler function uv.signal_start(signal, "sigint", function(signal) print("got " .. signal .. ", shutting down") os.exit(1) end) ``` ### `uv.new_signal()` Creates and initializes a new `uv_signal_t`. Returns the Lua userdata wrapping it. **Returns:** `uv_signal_t userdata` or `fail` ### `uv.signal_start(signal, signum, callback)` > method form `signal:start(signum, callback)` **Parameters:** - `signal`: `uv_signal_t userdata` - `signum`: `integer` or `string` - `callback`: `callable` - `signum`: `string` Start the handle with the given callback, watching for the given signal. **Returns:** `0` or `fail` ### `uv.signal_start_oneshot(signal, signum, callback)` > method form `signal:start_oneshot(signum, callback)` **Parameters:** - `signal`: `uv_signal_t userdata` - `signum`: `integer` or `string` - `callback`: `callable` - `signum`: `string` Same functionality as `uv.signal_start()` but the signal handler is reset the moment the signal is received. **Returns:** `0` or `fail` ### `uv.signal_stop(signal)` > method form `signal:stop()` **Parameters:** - `signal`: `uv_signal_t userdata` Stop the handle, the callback will no longer be called. **Returns:** `0` or `fail` ## `uv_process_t` — Process handle [`uv_process_t`]: #uv_process_t--process-handle > [`uv_handle_t`][] functions also apply. Process handles will spawn a new process and allow the user to control it and establish communication channels with it using streams. ### `uv.disable_stdio_inheritance()` Disables inheritance for file descriptors / handles that this process inherited from its parent. The effect is that child processes spawned by this process don't accidentally inherit these handles. It is recommended to call this function as early in your program as possible, before the inherited file descriptors can be closed or duplicated. **Returns:** Nothing. **Note:** This function works on a best-effort basis: there is no guarantee that libuv can discover all file descriptors that were inherited. In general it does a better job on Windows than it does on Unix. ### `uv.spawn(path, options, on_exit)` **Parameters:** - `path`: `string` - `options`: `table` (see below) - `on_exit`: `callable` - `code`: `integer` - `signal`: `integer` Initializes the process handle and starts the process. If the process is successfully spawned, this function will return the handle and pid of the child process. Possible reasons for failing to spawn would include (but not be limited to) the file to execute not existing, not having permissions to use the setuid or setgid specified, or not having enough memory to allocate for the new process. ```lua local stdin = uv.new_pipe() local stdout = uv.new_pipe() local stderr = uv.new_pipe() print("stdin", stdin) print("stdout", stdout) print("stderr", stderr) local handle, pid = uv.spawn("cat", { stdio = {stdin, stdout, stderr} }, function(code, signal) -- on exit print("exit code", code) print("exit signal", signal) end) print("process opened", handle, pid) uv.read_start(stdout, function(err, data) assert(not err, err) if data then print("stdout chunk", stdout, data) else print("stdout end", stdout) end end) uv.read_start(stderr, function(err, data) assert(not err, err) if data then print("stderr chunk", stderr, data) else print("stderr end", stderr) end end) uv.write(stdin, "Hello World") uv.shutdown(stdin, function() print("stdin shutdown", stdin) uv.close(handle, function() print("process closed", handle, pid) end) end) ``` The `options` table accepts the following fields: - `options.args` - Command line arguments as a list of string. The first string should be the path to the program. On Windows, this uses CreateProcess which concatenates the arguments into a string. This can cause some strange errors. (See `options.verbatim` below for Windows.) - `options.stdio` - Set the file descriptors that will be made available to the child process. The convention is that the first entries are stdin, stdout, and stderr. (**Note**: On Windows, file descriptors after the third are available to the child process only if the child processes uses the MSVCRT runtime.) - `options.env` - Set environment variables for the new process. - `options.cwd` - Set the current working directory for the sub-process. - `options.uid` - Set the child process' user id. - `options.gid` - Set the child process' group id. - `options.verbatim` - If true, do not wrap any arguments in quotes, or perform any other escaping, when converting the argument list into a command line string. This option is only meaningful on Windows systems. On Unix it is silently ignored. - `options.detached` - If true, spawn the child process in a detached state - this will make it a process group leader, and will effectively enable the child to keep running after the parent exits. Note that the child process will still keep the parent's event loop alive unless the parent process calls `uv.unref()` on the child's process handle. - `options.hide` - If true, hide the subprocess console window that would normally be created. This option is only meaningful on Windows systems. On Unix it is silently ignored. The `options.stdio` entries can take many shapes. - If they are numbers, then the child process inherits that same zero-indexed fd from the parent process. - If `uv_stream_t` handles are passed in, those are used as a read-write pipe or inherited stream depending if the stream has a valid fd. - Including `nil` placeholders means to ignore that fd in the child process. When the child process exits, `on_exit` is called with an exit code and signal. **Returns:** `uv_process_t userdata`, `integer` ### `uv.process_kill(process, signum)` > method form `process:kill(signum)` **Parameters:** - `process`: `uv_process_t userdata` - `signum`: `integer` or `string` Sends the specified signal to the given process handle. Check the documentation on `uv_signal_t` for signal support, specially on Windows. **Returns:** `0` or `fail` ### `uv.kill(pid, signum)` **Parameters:** - `pid`: `integer` - `signum`: `integer` or `string` Sends the specified signal to the given PID. Check the documentation on `uv_signal_t` for signal support, specially on Windows. **Returns:** `0` or `fail` ## `uv_stream_t` — Stream handle [`uv_stream_t`]: #uv_stream_t--stream-handle > [`uv_handle_t`][] functions also apply. Stream handles provide an abstraction of a duplex communication channel. [`uv_stream_t`][] is an abstract type, libuv provides 3 stream implementations in the form of [`uv_tcp_t`][], [`uv_pipe_t`][] and [`uv_tty_t`][]. ### `uv.shutdown(stream, [callback])` > method form `stream:shutdown([callback])` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` - `callback`: `callable` or `nil` - `err`: `nil` or `string` Shutdown the outgoing (write) side of a duplex stream. It waits for pending write requests to complete. The callback is called after shutdown is complete. **Returns:** `uv_shutdown_t userdata` or `fail` ### `uv.listen(stream, backlog, callback)` > method form `stream:listen(backlog, callback)` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` - `backlog`: `integer` - `callback`: `callable` - `err`: `nil` or `string` Start listening for incoming connections. `backlog` indicates the number of connections the kernel might queue, same as `listen(2)`. When a new incoming connection is received the callback is called. **Returns:** `0` or `fail` ### `uv.accept(stream, client_stream)` > method form `stream:accept(client_stream)` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` - `client_stream`: `userdata` for sub-type of `uv_stream_t` This call is used in conjunction with `uv.listen()` to accept incoming connections. Call this function after receiving a callback to accept the connection. When the connection callback is called it is guaranteed that this function will complete successfully the first time. If you attempt to use it more than once, it may fail. It is suggested to only call this function once per connection call. **Returns:** `0` or `fail` ```lua server:listen(128, function (err) local client = uv.new_tcp() server:accept(client) end) ``` ### `uv.read_start(stream, callback)` > method form `stream:read_start(callback)` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` - `callback`: `callable` - `err`: `nil` or `string` - `data`: `string` or `nil` Read data from an incoming stream. The callback will be made several times until there is no more data to read or `uv.read_stop()` is called. When we've reached EOF, `data` will be `nil`. **Returns:** `0` or `fail` ```lua stream:read_start(function (err, chunk) if err then -- handle read error elseif chunk then -- handle data else -- handle disconnect end end) ``` ### `uv.read_stop(stream)` > method form `stream:read_stop()` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` Stop reading data from the stream. The read callback will no longer be called. This function is idempotent and may be safely called on a stopped stream. **Returns:** `0` or `fail` ### `uv.write(stream, data, [callback])` > method form `stream:write(data, [callback])` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` - `data`: `buffer` - `callback`: `callable` or `nil` - `err`: `nil` or `string` Write data to stream. `data` can either be a Lua string or a table of strings. If a table is passed in, the C backend will use writev to send all strings in a single system call. The optional `callback` is for knowing when the write is complete. **Returns:** `uv_write_t userdata` or `fail` ### `uv.write2(stream, data, send_handle, [callback])` > method form `stream:write2(data, send_handle, [callback])` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` - `data`: `buffer` - `send_handle`: `userdata` for sub-type of `uv_stream_t` - `callback`: `callable` or `nil` - `err`: `nil` or `string` Extended write function for sending handles over a pipe. The pipe must be initialized with `ipc` option `true`. **Returns:** `uv_write_t userdata` or `fail` **Note:** `send_handle` must be a TCP socket or pipe, which is a server or a connection (listening or connected state). Bound sockets or pipes will be assumed to be servers. ### `uv.try_write(stream, data)` > method form `stream:try_write(data)` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` - `data`: `buffer` Same as `uv.write()`, but won't queue a write request if it can't be completed immediately. Will return number of bytes written (can be less than the supplied buffer size). **Returns:** `integer` or `fail` ### `uv.is_readable(stream)` > method form `stream:is_readable()` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` Returns `true` if the stream is readable, `false` otherwise. **Returns:** `boolean` ### `uv.is_writable(stream)` > method form `stream:is_writable()` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` Returns `true` if the stream is writable, `false` otherwise. **Returns:** `boolean` ### `uv.stream_set_blocking(stream, blocking)` > method form `stream:set_blocking(blocking)` **Parameters:** - `stream`: `userdata` for sub-type of `uv_stream_t` - `blocking`: `boolean` Enable or disable blocking mode for a stream. When blocking mode is enabled all writes complete synchronously. The interface remains unchanged otherwise, e.g. completion or failure of the operation will still be reported through a callback which is made asynchronously. **Returns:** `0` or `fail` **Warning**: Relying too much on this API is not recommended. It is likely to change significantly in the future. Currently this only works on Windows and only for `uv_pipe_t` handles. Also libuv currently makes no ordering guarantee when the blocking mode is changed after write requests have already been submitted. Therefore it is recommended to set the blocking mode immediately after opening or creating the stream. ### `uv.stream_get_write_queue_size()` > method form `stream:get_write_queue_size()` Returns the stream's write queue size. **Returns:** `integer` ## `uv_tcp_t` — TCP handle [`uv_tcp_t`]: #uv_tcp_t--tcp-handle > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. TCP handles are used to represent both TCP streams and servers. ### `uv.new_tcp([flags])` **Parameters:** - `flags`: `string` or `nil` Creates and initializes a new `uv_tcp_t`. Returns the Lua userdata wrapping it. Flags may be a family string: `"unix"`, `"inet"`, `"inet6"`, `"ipx"`, `"netlink"`, `"x25"`, `"ax25"`, `"atmpvc"`, `"appletalk"`, or `"packet"`. **Returns:** `uv_tcp_t userdata` or `fail` ### `uv.tcp_open(tcp, sock)` > method form `tcp:open(sock)` **Parameters:** - `tcp`: `uv_tcp_t userdata` - `sock`: `integer` Open an existing file descriptor or SOCKET as a TCP handle. **Returns:** `0` or `fail` **Note:** The passed file descriptor or SOCKET is not checked for its type, but it's required that it represents a valid stream socket. ### `uv.tcp_nodelay(tcp, enable)` > method form `tcp:nodelay(enable)` **Parameters:** - `tcp`: `uv_tcp_t userdata` - `enable`: `boolean` Enable / disable Nagle's algorithm. **Returns:** `0` or `fail` ### `uv.tcp_keepalive(tcp, enable, [delay])` > method form `tcp:keepalive(enable, [delay])` **Parameters:** - `tcp`: `uv_tcp_t userdata` - `enable`: `boolean` - `delay`: `integer` or `nil` Enable / disable TCP keep-alive. `delay` is the initial delay in seconds, ignored when enable is `false`. **Returns:** `0` or `fail` ### `uv.tcp_simultaneous_accepts(tcp, enable)` > method form `tcp:simultaneous_accepts(enable)` **Parameters:** - `tcp`: `uv_tcp_t userdata` - `enable`: `boolean` Enable / disable simultaneous asynchronous accept requests that are queued by the operating system when listening for new TCP connections. This setting is used to tune a TCP server for the desired performance. Having simultaneous accepts can significantly improve the rate of accepting connections (which is why it is enabled by default) but may lead to uneven load distribution in multi-process setups. **Returns:** `0` or `fail` ### `uv.tcp_bind(tcp, host, port, [flags])` > method form `tcp:bind(host, port, [flags])` **Parameters:** - `tcp`: `uv_tcp_t userdata` - `host`: `string` - `port`: `integer` - `flags`: `table` or `nil` - `ipv6only`: `boolean` Bind the handle to an host and port. `host` should be an IP address and not a domain name. Any `flags` are set with a table with field `ipv6only` equal to `true` or `false`. When the port is already taken, you can expect to see an `EADDRINUSE` error from either `uv.tcp_bind()`, `uv.listen()` or `uv.tcp_connect()`. That is, a successful call to this function does not guarantee that the call to `uv.listen()` or `uv.tcp_connect()` will succeed as well. Use a port of `0` to let the OS assign an ephemeral port. You can look it up later using `uv.tcp_getsockname()`. **Returns:** `0` or `fail` ### `uv.tcp_getpeername(tcp)` > method form `tcp:getpeername()` **Parameters:** - `tcp`: `uv_tcp_t userdata` Get the current address to which the handle is bound. **Returns:** `table` or `fail` - `ip` : `string` - `family` : `string` - `port` : `integer` ### `uv.tcp_getsockname(tcp)` > method form `tcp:getsockname()` **Parameters:** - `tcp`: `uv_tcp_t userdata` Get the address of the peer connected to the handle. **Returns:** `table` or `fail` - `ip` : `string` - `family` : `string` - `port` : `integer` ### `uv.tcp_connect(tcp, host, port, callback)` > method form `tcp:connect(host, port, callback)` **Parameters:** - `tcp`: `uv_tcp_t userdata` - `host`: `string` - `port`: `integer` - `callback`: `callable` - `err`: `nil` or `string` Establish an IPv4 or IPv6 TCP connection. **Returns:** `uv_connect_t userdata` or `fail` ```lua local client = uv.new_tcp() client:connect("127.0.0.1", 8080, function (err) -- check error and carry on. end) ``` ### `uv.tcp_write_queue_size(tcp)` > method form `tcp:write_queue_size()` **Deprecated:** Please use `uv.stream_get_write_queue_size()` instead. ### `uv.tcp_close_reset([callback])` > method form `tcp:close_reset([callback])` **Parameters:** - `tcp`: `uv_tcp_t userdata` - `callback`: `callable` or `nil` Resets a TCP connection by sending a RST packet. This is accomplished by setting the SO_LINGER socket option with a linger interval of zero and then calling `uv.close()`. Due to some platform inconsistencies, mixing of `uv.shutdown()` and `uv.tcp_close_reset()` calls is not allowed. **Returns:** `0` or `fail` ## `uv_pipe_t` — Pipe handle [`uv_pipe_t`]: #uv_pipe_t--pipe-handle > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. Pipe handles provide an abstraction over local domain sockets on Unix and named pipes on Windows. ```lua local pipe = uv.new_pipe(false) pipe:bind('/tmp/sock.test') pipe:listen(128, function() local client = uv.new_pipe(false) pipe:accept(client) client:write("hello!\n") client:close() end) ``` ### `uv.new_pipe([ipc])` **Parameters:** - `ipc`: `boolean` or `nil` (default: `false`) Creates and initializes a new `uv_pipe_t`. Returns the Lua userdata wrapping it. The `ipc` argument is a boolean to indicate if this pipe will be used for handle passing between processes. **Returns:** `uv_pipe_t userdata` or `fail` ### `uv.pipe_open(pipe, fd)` > method form `pipe:open(fd)` **Parameters:** - `pipe`: `uv_pipe_t userdata` - `fd`: `integer` Open an existing file descriptor or [`uv_handle_t`][] as a pipe. **Returns:** `0` or `fail` **Note**: The file descriptor is set to non-blocking mode. ### `uv.pipe_bind(pipe, name)` > method form `pipe:bind(name)` **Parameters:** - `pipe`: `uv_pipe_t userdata` - `name`: `string` Bind the pipe to a file path (Unix) or a name (Windows). **Returns:** `0` or `fail` **Note**: Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, typically between 92 and 108 bytes. ### `uv.pipe_connect(pipe, name, [callback])` > method form `pipe:connect(name, [callback])` **Parameters:** - `pipe`: `uv_pipe_t userdata` - `name`: `string` - `callback`: `callable` or `nil` - `err`: `nil` or `string` Connect to the Unix domain socket or the named pipe. **Returns:** `uv_connect_t userdata` or `fail` **Note**: Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, typically between 92 and 108 bytes. ### `uv.pipe_getsockname(pipe)` > method form `pipe:getsockname()` **Parameters:** - `pipe`: `uv_pipe_t userdata` Get the name of the Unix domain socket or the named pipe. **Returns:** `string` or `fail` ### `uv.pipe_getpeername(pipe)` > method form `pipe:getpeername()` **Parameters:** - `pipe`: `uv_pipe_t userdata` Get the name of the Unix domain socket or the named pipe to which the handle is connected. **Returns:** `string` or `fail` ### `uv.pipe_pending_instances(pipe, count)` > method form `pipe:pending_instances(count)` **Parameters:** - `pipe`: `uv_pipe_t userdata` - `count`: `integer` Set the number of pending pipe instance handles when the pipe server is waiting for connections. **Returns:** Nothing. **Note**: This setting applies to Windows only. ### `uv.pipe_pending_count(pipe)` > method form `pipe:pending_count()` **Parameters:** - `pipe`: `uv_pipe_t userdata` Returns the pending pipe count for the named pipe. **Returns:** `integer` ### `uv.pipe_pending_type(pipe)` > method form `pipe:pending_type()` **Parameters:** - `pipe`: `uv_pipe_t userdata` Used to receive handles over IPC pipes. First - call `uv.pipe_pending_count()`, if it's > 0 then initialize a handle of the given type, returned by `uv.pipe_pending_type()` and call `uv.accept(pipe, handle)`. **Returns:** `string` ## `uv_tty_t` — TTY handle [`uv_tty_t`]: #uv_tty_t--tty-handle > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. TTY handles represent a stream for the console. ```lua -- Simple echo program local stdin = uv.new_tty(0, true) local stdout = uv.new_tty(1, false) stdin:read_start(function (err, data) assert(not err, err) if data then stdout:write(data) else stdin:close() stdout:close() end end) ``` ### `uv.new_tty(fd, readable)` **Parameters:** - `fd`: `integer` - `readable`: `boolean` Initialize a new TTY stream with the given file descriptor. Usually the file descriptor will be: - 0 - stdin - 1 - stdout - 2 - stderr On Unix this function will determine the path of the fd of the terminal using ttyname_r(3), open it, and use it if the passed file descriptor refers to a TTY. This lets libuv put the tty in non-blocking mode without affecting other processes that share the tty. This function is not thread safe on systems that don’t support ioctl TIOCGPTN or TIOCPTYGNAME, for instance OpenBSD and Solaris. **Returns:** `uv_tty_t userdata` or `fail` **Note:** If reopening the TTY fails, libuv falls back to blocking writes. ### `uv.tty_set_mode(tty, mode)` > method form `tty:set_mode(mode)` **Parameters:** - `tty`: `uv_tty_t userdata` - `mode`: `integer` Set the TTY using the specified terminal mode. Parameter `mode` is a C enum with the following values: - 0 - UV_TTY_MODE_NORMAL: Initial/normal terminal mode - 1 - UV_TTY_MODE_RAW: Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) - 2 - UV_TTY_MODE_IO: Binary-safe I/O mode for IPC (Unix-only) **Returns:** `0` or `fail` ### `uv.tty_reset_mode()` To be called when the program exits. Resets TTY settings to default values for the next process to take over. This function is async signal-safe on Unix platforms but can fail with error code `EBUSY` if you call it when execution is inside `uv.tty_set_mode()`. **Returns:** `0` or `fail` ### `uv.tty_get_winsize(tty)` > method form `tty:get_winsize()` **Parameters:** - `tty`: `uv_tty_t userdata` Gets the current Window width and height. **Returns:** `integer, integer` or `fail` ### `uv.tty_set_vterm_state(state)` **Parameters:** - `state`: `string` Controls whether console virtual terminal sequences are processed by libuv or console. Useful in particular for enabling ConEmu support of ANSI X3.64 and Xterm 256 colors. Otherwise Windows10 consoles are usually detected automatically. State may be a family string: `"supported"` or `"unsupported"`. This function is only meaningful on Windows systems. On Unix it is silently ignored. **Returns:** none ### `uv.tty_get_vterm_state()` Get the current state of whether console virtual terminal sequences are handled by libuv or the console. The return value is `"supported"` or `"unsupported"`. This function is not implemented on Unix, where it returns `ENOTSUP`. **Returns:** `string` or `fail` ## `uv_udp_t` — UDP handle [`uv_udp_t`]: #uv_udp_t--udp-handle > [`uv_handle_t`][] functions also apply. UDP handles encapsulate UDP communication for both clients and servers. ### `uv.new_udp([flags])` **Parameters:** - `flags`: `string` or `nil` Creates and initializes a new `uv_udp_t`. Returns the Lua userdata wrapping it. The actual socket is created lazily. Flags may be a family string: `"unix"`, `"inet"`, `"inet6"`, `"ipx"`, `"netlink"`, `"x25"`, `"ax25"`, `"atmpvc"`, `"appletalk"`, or `"packet"`. **Returns:** `uv_udp_t userdata` or `fail` ### `uv.udp_get_send_queue_size()` > method form `udp:get_send_queue_size()` Returns the handle's send queue size. **Returns:** `integer` ### `uv.udp_get_send_queue_count()` > method form `udp:get_send_count_size()` Returns the handle's send queue count. **Returns:** `integer` ### `uv.udp_open(udp, fd)` > method form `udp:open(fd)` **Parameters:** - `udp`: `uv_udp_t userdata` - `fd`: `integer` Opens an existing file descriptor or Windows SOCKET as a UDP handle. Unix only: The only requirement of the sock argument is that it follows the datagram contract (works in unconnected mode, supports sendmsg()/recvmsg(), etc). In other words, other datagram-type sockets like raw sockets or netlink sockets can also be passed to this function. The file descriptor is set to non-blocking mode. Note: The passed file descriptor or SOCKET is not checked for its type, but it's required that it represents a valid datagram socket. **Returns:** `0` or `fail` ### `uv.udp_bind(udp, host, port, [flags])` > method form `udp:bind(host, port, [flags])` **Parameters:** - `udp`: `uv_udp_t userdata` - `host`: `string` - `port`: `number` - `flags`: `table` or `nil` - `ipv6only`: `boolean` Bind the UDP handle to an IP address and port. Any `flags` are set with a table with fields `reuseaddr` or `ipv6only` equal to `true` or `false`. **Returns:** `0` or `fail` ### `uv.udp_getsockname(udp)` > method form `udp:getsockname()` **Parameters:** - `udp`: `uv_udp_t userdata` Get the local IP and port of the UDP handle. **Returns:** `table` or `fail` - `ip` : `string` - `family` : `string` - `port` : `integer` ### `uv.udp_getpeername(udp)` > method form `udp:getpeername()` **Parameters:** - `udp`: `uv_udp_t userdata` Get the remote IP and port of the UDP handle on connected UDP handles. **Returns:** `table` or `fail` - `ip` : `string` - `family` : `string` - `port` : `integer` ### `uv.udp_set_membership(udp, multicast_addr, interface_addr, membership)` > method form `udp:set_membership(multicast_addr, interface_addr, membership)` **Parameters:** - `udp`: `uv_udp_t userdata` - `multicast_addr`: `string` - `interface_addr`: `string` - `membership`: `string` Set membership for a multicast address. `multicast_addr` is multicast address to set membership for. `interface_addr` is interface address. `membership` can be the string `"leave"` or `"join"`. **Returns:** `0` or `fail` ### `uv.udp_set_multicast_loop(udp, on)` > method form `udp:set_multicast_loop(on)` **Parameters:** - `udp`: `uv_udp_t userdata` - `on`: `boolean` Set IP multicast loop flag. Makes multicast packets loop back to local sockets. **Returns:** `0` or `fail` ### `uv.udp_set_multicast_ttl(udp, ttl)` > method form `udp:set_multicast_ttl(ttl)` **Parameters:** - `udp`: `uv_udp_t userdata` - `ttl`: `integer` Set the multicast ttl. `ttl` is an integer 1 through 255. **Returns:** `0` or `fail` ### `uv.udp_set_multicast_interface(udp, interface_addr)` > method form `udp:set_multicast_interface(interface_addr)` **Parameters:** - `udp`: `uv_udp_t userdata` - `interface_addr`: `string` Set the multicast interface to send or receive data on. **Returns:** `0` or `fail` ### `uv.udp_set_broadcast(udp, on)` > method form `udp:set_broadcast(on)` **Parameters:** - `udp`: `uv_udp_t userdata` - `on`: `boolean` Set broadcast on or off. **Returns:** `0` or `fail` ### `uv.udp_set_ttl(udp, ttl)` > method form `udp:set_ttl(ttl)` **Parameters:** - `udp`: `uv_udp_t userdata` - `ttl`: `integer` Set the time to live. `ttl` is an integer 1 through 255. **Returns:** `0` or `fail` ### `uv.udp_send(udp, data, host, port, callback)` > method form `udp:send(data, host, port, callback)` **Parameters:** - `udp`: `uv_udp_t userdata` - `data`: `buffer` - `host`: `string` - `port`: `integer` - `callback`: `callable` - `err`: `nil` or `string` Send data over the UDP socket. If the socket has not previously been bound with `uv.udp_bind()` it will be bound to `0.0.0.0` (the "all interfaces" IPv4 address) and a random port number. **Returns:** `uv_udp_send_t userdata` or `fail` ### `uv.udp_try_send(udp, data, host, port)` > method form `udp:try_send(data, host, port)` **Parameters:** - `udp`: `uv_udp_t userdata` - `data`: `buffer` - `host`: `string` - `port`: `integer` Same as `uv.udp_send()`, but won't queue a send request if it can't be completed immediately. **Returns:** `integer` or `fail` ### `uv.udp_recv_start(udp, callback)` > method form `udp:recv_start(callback)` **Parameters:** - `udp`: `uv_udp_t userdata` - `callback`: `callable` - `err`: `nil` or `string` - `data`: `string` or `nil` - `addr`: `table` or `nil` - `ip`: `string` - `port`: `integer` - `family`: `string` - `flags`: `table` - `partial`: `boolean` or `nil` - `mmsg_chunk`: `boolean` or `nil` Prepare for receiving data. If the socket has not previously been bound with `uv.udp_bind()` it is bound to `0.0.0.0` (the "all interfaces" IPv4 address) and a random port number. **Returns:** `0` or `fail` ### `uv.udp_recv_stop(udp)` > method form `udp:recv_stop()` **Parameters:** - `udp`: `uv_udp_t userdata` Stop listening for incoming datagrams. **Returns:** `0` or `fail` ### `uv.udp_connect(udp, host, port)` > method form `udp:connect(host, port)` **Parameters:** - `udp`: `uv_udp_t userdata` - `host`: `string` - `port`: `integer` Associate the UDP handle to a remote address and port, so every message sent by this handle is automatically sent to that destination. Calling this function with a NULL addr disconnects the handle. Trying to call `uv.udp_connect()` on an already connected handle will result in an `EISCONN` error. Trying to disconnect a handle that is not connected will return an `ENOTCONN` error. **Returns:** `0` or `fail` ## `uv_fs_event_t` — FS Event handle [`uv_fs_event_t`]: #uv_fs_event_t--fs-event-handle > [`uv_handle_t`][] functions also apply. FS Event handles allow the user to monitor a given path for changes, for example, if the file was renamed or there was a generic change in it. This handle uses the best backend for the job on each platform. ### `uv.new_fs_event()` Creates and initializes a new `uv_fs_event_t`. Returns the Lua userdata wrapping it. **Returns:** `uv_fs_event_t userdata` or `fail` ### `uv.fs_event_start(fs_event, path, flags, callback)` > method form `fs_event:start(path, flags, callback)` **Parameters:** - `fs_event`: `uv_fs_event_t userdata` - `path`: `string` - `flags`: `table` - `watch_entry`: `boolean` or `nil` (default: `false`) - `stat`: `boolean` or `nil` (default: `false`) - `recursive`: `boolean` or `nil` (default: `false`) - `callback`: `callable` - `err`: `nil` or `string` - `filename`: `string` - `events`: `table` - `change`: `boolean` or `nil` - `rename`: `boolean` or `nil` Start the handle with the given callback, which will watch the specified path for changes. **Returns:** `0` or `fail` ### `uv.fs_event_stop()` > method form `fs_event:stop()` Stop the handle, the callback will no longer be called. **Returns:** `0` or `fail` ### `uv.fs_event_getpath()` > method form `fs_event:getpath()` Get the path being monitored by the handle. **Returns:** `string` or `fail` ## `uv_fs_poll_t` — FS Poll handle [`uv_fs_poll_t`]: #uv_fs_poll_t--fs-poll-handle > [`uv_handle_t`][] functions also apply. FS Poll handles allow the user to monitor a given path for changes. Unlike `uv_fs_event_t`, fs poll handles use `stat` to detect when a file has changed so they can work on file systems where fs event handles can't. ### `uv.new_fs_poll()` Creates and initializes a new `uv_fs_poll_t`. Returns the Lua userdata wrapping it. **Returns:** `uv_fs_poll_t userdata` or `fail` ### `uv.fs_poll_start(fs_poll, path, interval, callback)` > method form `fs_poll:start(path, interval, callback)` **Parameters:** - `fs_event`: `uv_fs_event_t userdata` - `path`: `string` - `interval`: `integer` - `callback`: `callable` - `err`: `nil` or `string` - `prev`: `table` or `nil` (see `uv.fs_stat`) - `curr`: `table` or `nil` (see `uv.fs_stat`) Check the file at `path` for changes every `interval` milliseconds. **Note:** For maximum portability, use multi-second intervals. Sub-second intervals will not detect all changes on many file systems. **Returns:** `0` or `fail` ### `uv.fs_poll_stop()` > method form `fs_poll:stop()` Stop the handle, the callback will no longer be called. **Returns:** `0` or `fail` ### `uv.fs_poll_getpath()` > method form `fs_poll:getpath()` Get the path being monitored by the handle. **Returns:** `string` or `fail` ## File system operations [File system operations]: #file-system-operations Most file system functions can operate synchronously or asynchronously. When a synchronous version is called (by omitting a callback), the function will immediately return the results of the FS call. When an asynchronous version is called (by providing a callback), the function will immediately return a `uv_fs_t userdata` and asynchronously execute its callback; if an error is encountered, the first and only argument passed to the callback will be the `err` error string; if the operation completes successfully, the first argument will be `nil` and the remaining arguments will be the results of the FS call. Synchronous and asynchronous versions of `readFile` (with naive error handling) are implemented below as an example: ```lua local function readFileSync(path) local fd = assert(uv.fs_open(path, "r", 438)) local stat = assert(uv.fs_fstat(fd)) local data = assert(uv.fs_read(fd, stat.size, 0)) assert(uv.fs_close(fd)) return data end local data = readFileSync("main.lua") print("synchronous read", data) ``` ```lua local function readFile(path, callback) uv.fs_open(path, "r", 438, function(err, fd) assert(not err, err) uv.fs_fstat(fd, function(err, stat) assert(not err, err) uv.fs_read(fd, stat.size, 0, function(err, data) assert(not err, err) uv.fs_close(fd, function(err) assert(not err, err) return callback(data) end) end) end) end) end readFile("main.lua", function(data) print("asynchronous read", data) end) ``` ### `uv.fs_close(fd, [callback])` **Parameters:** - `fd`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `close(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_open(path, flags, mode, [callback])` **Parameters:** - `path`: `string` - `flags`: `string` or `integer` - `mode`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `fd`: `integer` or `nil` Equivalent to `open(2)`. Access `flags` may be an integer or one of: `"r"`, `"rs"`, `"sr"`, `"r+"`, `"rs+"`, `"sr+"`, `"w"`, `"wx"`, `"xw"`, `"w+"`, `"wx+"`, `"xw+"`, `"a"`, `"ax"`, `"xa"`, `"a+"`, `"ax+"`, or "`xa+`". **Returns (sync version):** `integer` or `fail` **Returns (async version):** `uv_fs_t userdata` **Note:** On Windows, libuv uses `CreateFileW` and thus the file is always opened in binary mode. Because of this, the `O_BINARY` and `O_TEXT` flags are not supported. ### `uv.fs_read(fd, size, offset, [callback])` **Parameters:** - `fd`: `integer` - `size`: `integer` - `offset`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `data`: `string` or `nil` Equivalent to `preadv(2)`. Returns any data. An empty string indicates EOF. **Returns (sync version):** `string` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_unlink(path, [callback])` **Parameters:** - `path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `unlink(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_write(fd, data, offset, [callback])` **Parameters:** - `fd`: `integer` - `data`: `buffer` - `offset`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `bytes`: `integer` or `nil` Equivalent to `pwritev(2)`. Returns the number of bytes written. **Returns (sync version):** `integer` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_mkdir(path, mode, [callback])` **Parameters:** - `path`: `string` - `mode`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `mkdir(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_mkdtemp(template, [callback])` **Parameters:** - `template`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `path`: `string` or `nil` Equivalent to `mkdtemp(3)`. **Returns (sync version):** `string` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_mkstemp(template, [callback])` **Parameters:** - `template`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `fd`: `integer` or `nil` - `path`: `string` or `nil` Equivalent to `mkstemp(3)`. Returns a temporary file handle and filename. **Returns (sync version):** `integer, string` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_rmdir(path, [callback])` **Parameters:** - `path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `rmdir(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_scandir(path, [callback])` **Parameters:** - `path`: `string` - `callback`: `callable` - `err`: `nil` or `string` - `success`: `uv_fs_t userdata` or `nil` Equivalent to `scandir(3)`, with a slightly different API. Returns a handle that the user can pass to `uv.fs_scandir_next()`. **Note:** This function can be used synchronously or asynchronously. The request userdata is always synchronously returned regardless of whether a callback is provided and the same userdata is passed to the callback if it is provided. **Returns:** `uv_fs_t userdata` or `fail` ### `uv.fs_scandir_next(fs)` **Parameters:** - `fs`: `uv_fs_t userdata` Called on a `uv_fs_t` returned by `uv.fs_scandir()` to get the next directory entry data as a `name, type` pair. When there are no more entries, `nil` is returned. **Note:** This function only has a synchronous version. See `uv.fs_opendir` and its related functions for an asynchronous version. **Returns:** `string, string` or `nil` or `fail` ### `uv.fs_stat(path, [callback])` **Parameters:** - `path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `stat`: `table` or `nil` (see below) Equivalent to `stat(2)`. **Returns (sync version):** `table` or `fail` - `dev` : `integer` - `mode` : `integer` - `nlink` : `integer` - `uid` : `integer` - `gid` : `integer` - `rdev` : `integer` - `ino` : `integer` - `size` : `integer` - `blksize` : `integer` - `blocks` : `integer` - `flags` : `integer` - `gen` : `integer` - `atime` : `table` - `sec` : `integer` - `nsec` : `integer` - `mtime` : `table` - `sec` : `integer` - `nsec` : `integer` - `ctime` : `table` - `sec` : `integer` - `nsec` : `integer` - `birthtime` : `table` - `sec` : `integer` - `nsec` : `integer` - `type` : `string` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_fstat(fd, [callback])` **Parameters:** - `fd`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `stat`: `table` or `nil` (see `uv.fs_stat`) Equivalent to `fstat(2)`. **Returns (sync version):** `table` or `fail` (see `uv.fs_stat`) **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_lstat(path, [callback])` **Parameters:** - `fd`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `stat`: `table` or `nil` (see `uv.fs_stat`) Equivalent to `lstat(2)`. **Returns (sync version):** `table` or `fail` (see `uv.fs_stat`) **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_rename(path, new_path, [callback])` **Parameters:** - `path`: `string` - `new_path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `rename(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_fsync(fd, [callback])` **Parameters:** - `fd`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `fsync(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_fdatasync(fd, [callback])` **Parameters:** - `fd`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `fdatasync(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_ftruncate(fd, offset, [callback])` **Parameters:** - `fd`: `integer` - `offset`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `ftruncate(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_sendfile(out_fd, in_fd, in_offset, size, [callback])` **Parameters:** - `out_fd`: `integer` - `in_fd`: `integer` - `in_offset`: `integer` - `size`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `bytes`: `integer` or `nil` Limited equivalent to `sendfile(2)`. Returns the number of bytes written. **Returns (sync version):** `integer` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_access(path, mode, [callback])` **Parameters:** - `path`: `string` - `mode`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `permission`: `boolean` or `nil` Equivalent to `access(2)` on Unix. Windows uses `GetFileAttributesW()`. Access `mode` can be an integer or a string containing `""R"` or `"W"` or `"X"`. Returns `true` or `false` indicating access permission. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_chmod(path, mode, [callback])` **Parameters:** - `path`: `string` - `mode`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `chmod(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_fchmod(fd, mode, [callback])` **Parameters:** - `fd`: `integer` - `mode`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `fchmod(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_utime(path, atime, mtime, [callback])` **Parameters:** - `path`: `string` - `atime`: `number` - `mtime`: `number` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `utime(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_futime(fd, atime, mtime, [callback])` **Parameters:** - `fd`: `integer` - `atime`: `number` - `mtime`: `number` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `futime(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_link(path, new_path, [callback])` **Parameters:** - `path`: `string` - `new_path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `link(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_symlink(path, new_path, flags, [callback])` **Parameters:** - `path`: `string` - `new_path`: `string` - `flags`: `table` or `nil` - `dir`: `boolean` - `junction`: `boolean` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `symlink(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_readlink(path, [callback])` **Parameters:** - `path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `path`: `string` or `nil` Equivalent to `readlink(2)`. **Returns (sync version):** `string` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_realpath(path, [callback])` **Parameters:** - `path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `path`: `string` or `nil` Equivalent to `realpath(3)`. **Returns (sync version):** `string` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_chown(path, uid, gid, [callback])` **Parameters:** - `path`: `string` - `uid`: `integer` - `gid`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `chown(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_fchown(fd, uid, gid, [callback])` **Parameters:** - `fd`: `integer` - `uid`: `integer` - `gid`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `fchown(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_lchown(fd, uid, gid, [callback])` **Parameters:** - `fd`: `integer` - `uid`: `integer` - `gid`: `integer` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Equivalent to `lchown(2)`. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_copyfile(path, new_path, flags, [callback])` **Parameters:** - `path`: `string` - `new_path`: `string` - `flags`: `table` or `nil` - `excl`: `boolean` - `ficlone`: `boolean` - `ficlone_force`: `boolean` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Copies a file from path to new_path. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_opendir(path, [callback, [entries]])` **Parameters:** - `path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `dir`: `uv_dir_t userdata` or `nil` - `entries`: `integer` or `nil` Opens path as a directory stream. Returns a handle that the user can pass to `uv.fs_readdir()`. The `entries` parameter defines the maximum number of entries that should be returned by each call to `uv.fs_readdir()`. **Returns (sync version):** `uv_dir_t userdata` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_readdir(dir, [callback])` **Parameters:** - `dir`: `uv_dir_t userdata` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `entries`: `table` or `nil` (see below) Iterates over the directory stream `uv_dir_t` returned by a successful `uv.fs_opendir()` call. A table of data tables is returned where the number of entries `n` is equal to or less than the `entries` parameter used in the associated `uv.fs_opendir()` call. **Returns (sync version):** `table` or `fail` - `[1, 2, 3, ..., n]` : `table` - `name` : `string` - `type` : `string` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_closedir(dir, [callback])` **Parameters:** - `dir`: `uv_dir_t userdata` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `success`: `boolean` or `nil` Closes a directory stream returned by a successful `uv.fs_opendir()` call. **Returns (sync version):** `boolean` or `fail` **Returns (async version):** `uv_fs_t userdata` ### `uv.fs_statfs(path, [callback])` **Parameters:** - `path`: `string` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `table` or `nil` (see below) Equivalent to `statfs(2)`. **Returns** `table` or `nil` - `type` : `integer` - `bsize` : `integer` - `blocks` : `integer` - `bfree` : `integer` - `bavail` : `integer` - `files` : `integer` - `ffree` : `integer` ## Thread pool work scheduling [Thread pool work scheduling]: #thread-pool-work-scheduling Libuv provides a threadpool which can be used to run user code and get notified in the loop thread. This threadpool is internally used to run all file system operations, as well as `getaddrinfo` and `getnameinfo` requests. ```lua local function work_callback(a, b) return a + b end local function after_work_callback(c) print("The result is: " .. c) end local work = uv.new_work(work_callback, after_work_callback) work:queue(1, 2) -- output: "The result is: 3" ``` ### `uv.new_work(work_callback, after_work_callback)` **Parameters:** - `work_callback`: `function` - `...`: `threadargs` passed to/from `uv.queue_work(work_ctx, ...)` - `after_work_callback`: `function` - `...`: `threadargs` returned from `work_callback` Creates and initializes a new `luv_work_ctx_t` (not `uv_work_t`). Returns the Lua userdata wrapping it. **Returns:** `luv_work_ctx_t userdata` ### `uv.queue_work(work_ctx, ...)` > method form `work_ctx:queue(...)` **Parameters:** - `work_ctx`: `luv_work_ctx_t userdata` - `...`: `threadargs` Queues a work request which will run `work_callback` in a new Lua state in a thread from the threadpool with any additional arguments from `...`. Values returned from `work_callback` are passed to `after_work_callback`, which is called in the main loop thread. **Returns:** `boolean` or `fail` ## DNS utility functions [DNS utility functions]: #dns-utility-functions ### `uv.getaddrinfo(host, service, [hints, [callback]])` **Parameters:** - `host`: `string` or `nil` - `service`: `string` or `nil` - `hints`: `table` or `nil` - `family`: `integer` or `string` or `nil` - `socktype`: `integer` or `string` or `nil` - `protocol`: `integer` or `string` or `nil` - `addrconfig`: `boolean` or `nil` - `v4mapped`: `boolean` or `nil` - `all`: `boolean` or `nil` - `numerichost`: `boolean` or `nil` - `passive`: `boolean` or `nil` - `numericserv`: `boolean` or `nil` - `canonname`: `boolean` or `nil` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `addresses`: `table` or `nil` (see below) Equivalent to `getaddrinfo(3)`. Either `node` or `service` may be `nil` but not both. **Returns (sync version):** `table` or `fail` - `[1, 2, 3, ..., n]` : `table` - `addr` : `string` - `family` : `string` - `port` : `integer` or `nil` - `socktype` : `string` - `protocol` : `string` - `canonname` : `string` or `nil` **Returns (async version):** `uv_getaddrinfo_t userdata` or `fail` ### `uv.getnameinfo(address, [callback])` **Parameters:** - `address`: `table` - `ip`: `string` or `nil` - `port`: `integer` or `nil` - `family`: `string` or `integer` or `nil` - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `sring` - `host`: `string` or `nil` - `service`: `string` or `nil` Equivalent to `getnameinfo(3)`. **Returns (sync version):** `string, string` or `fail` **Returns (async version):** `uv_getnameinfo_t userdata` or `fail` ## Threading and synchronization utilities [Threading and synchronization utilities]: #threading-and-synchronization-utilities Libuv provides cross-platform implementations for multiple threading an synchronization primitives. The API largely follows the pthreads API. ### `uv.new_thread([options], entry, ...)` **Parameters:** - `options`: `table` or `nil` - `stack_size`: `integer` or `nil` - `entry`: `function` - `...`: `threadargs` passed to `entry` Creates and initializes a `luv_thread_t` (not `uv_thread_t`). Returns the Lua userdata wrapping it and asynchronously executes `entry`, which can be either a Lua function or a Lua function dumped to a string. Additional arguments `...` are passed to the `entry` function and an optional `options` table may be provided. Currently accepted `option` fields are `stack_size`. **Returns:** `luv_thread_t userdata` or `fail` ### `uv.thread_equal(thread, other_thread)` > method form `thread:equal(other_thread)` **Parameters:** - `thread`: `luv_thread_t userdata` - `other_thread`: `luv_thread_t userdata` Returns a boolean indicating whether two threads are the same. This function is equivalent to the `__eq` metamethod. **Returns:** `boolean` ### `uv.thread_self()` Returns the handle for the thread in which this is called. **Returns:** `luv_thread_t` ### `uv.thread_join(thread)` > method form `thread:join()` **Parameters:** - `thread`: `luv_thread_t userdata` Waits for the `thread` to finish executing its entry function. **Returns:** `boolean` or `fail` ### `uv.sleep(msec)` **Parameters:** - `msec`: `integer` Pauses the thread in which this is called for a number of milliseconds. **Returns:** Nothing. ## Miscellaneous utilities [Miscellaneous utilities]: #miscellaneous-utilities ### `uv.exepath()` Returns the executable path. **Returns:** `string` or `fail` ### `uv.cwd()` Returns the current working directory. **Returns:** `string` or `fail` ### `uv.chdir(cwd)` **Parameters:** - `cwd`: `string` Sets the current working directory with the string `cwd`. **Returns:** `0` or `fail` ### `uv.get_process_title()` Returns the title of the current process. **Returns:** `string` or `fail` ### `uv.set_process_title(title)` **Parameters:** - `title`: `string` Sets the title of the current process with the string `title`. **Returns:** `0` or `fail` ### `uv.get_total_memory()` Returns the current total system memory in bytes. **Returns:** `number` ### `uv.get_free_memory()` Returns the current free system memory in bytes. **Returns:** `number` ### `uv.get_constrained_memory()` Gets the amount of memory available to the process in bytes based on limits imposed by the OS. If there is no such constraint, or the constraint is unknown, 0 is returned. Note that it is not unusual for this value to be less than or greater than the total system memory. **Returns:** `number` ### `uv.resident_set_memory()` Returns the resident set size (RSS) for the current process. **Returns:** `integer` or `fail` ### `uv.getrusage()` Returns the resource usage. **Returns:** `table` or `fail` - `utime` : `table` (user CPU time used) - `sec` : `integer` - `usec` : `integer` - `stime` : `table` (system CPU time used) - `sec` : `integer` - `usec` : `integer` - `maxrss` : `integer` (maximum resident set size) - `ixrss` : `integer` (integral shared memory size) - `idrss` : `integer` (integral unshared data size) - `isrss` : `integer` (integral unshared stack size) - `minflt` : `integer` (page reclaims (soft page faults)) - `majflt` : `integer` (page faults (hard page faults)) - `nswap` : `integer` (swaps) - `inblock` : `integer` (block input operations) - `oublock` : `integer` (block output operations) - `msgsnd` : `integer` (IPC messages sent) - `msgrcv` : `integer` (IPC messages received) - `nsignals` : `integer` (signals received) - `nvcsw` : `integer` (voluntary context switches) - `nivcsw` : `integer` (involuntary context switches) ### `uv.cpu_info()` Returns information about the CPU(s) on the system as a table of tables for each CPU found. **Returns:** `table` or `fail` - `[1, 2, 3, ..., n]` : `table` - `model` : `string` - `speed` : `number` - `times` : `table` - `user` : `number` - `nice` : `number` - `sys` : `number` - `idle` : `number` - `irq` : `number` ### `uv.getpid()` **Deprecated:** Please use `uv.os_getpid()` instead. ### `uv.getuid()` Returns the user ID of the process. **Returns:** `integer` **Note:** This is not a libuv function and is not supported on Windows. ### `uv.getgid()` Returns the group ID of the process. **Returns:** `integer` **Note:** This is not a libuv function and is not supported on Windows. ### `uv.setuid(id)` **Parameters:** - `id`: `integer` Sets the user ID of the process with the integer `id`. **Returns:** Nothing. **Note:** This is not a libuv function and is not supported on Windows. ### `uv.setgid(id)` **Parameters:** - `id`: `integer` Sets the group ID of the process with the integer `id`. **Returns:** Nothing. **Note:** This is not a libuv function and is not supported on Windows. ### `uv.hrtime()` Returns a current high-resolution time in nanoseconds as a number. This is relative to an arbitrary time in the past. It is not related to the time of day and therefore not subject to clock drift. The primary use is for measuring time between intervals. **Returns:** `number` ### `uv.uptime()` Returns the current system uptime in seconds. **Returns:** `number` or `fail` ### `uv.print_all_handles()` Prints all handles associated with the main loop to stderr. The format is `[flags] handle-type handle-address`. Flags are `R` for referenced, `A` for active and `I` for internal. **Returns:** Nothing. **Note:** This is not available on Windows. **Warning:** This function is meant for ad hoc debugging, there are no API/ABI stability guarantees. ### `uv.print_active_handles()` The same as `uv.print_all_handles()` except only active handles are printed. **Returns:** Nothing. **Note:** This is not available on Windows. **Warning:** This function is meant for ad hoc debugging, there are no API/ABI stability guarantees. ### `uv.guess_handle(fd)` **Parameters:** - `fd`: `integer` Used to detect what type of stream should be used with a given file descriptor `fd`. Usually this will be used during initialization to guess the type of the stdio streams. **Returns:** `string` ### `uv.gettimeofday()` Cross-platform implementation of `gettimeofday(2)`. Returns the seconds and microseconds of a unix time as a pair. **Returns:** `integer, integer` or `fail` ### `uv.interface_addresses()` Returns address information about the network interfaces on the system in a table. Each table key is the name of the interface while each associated value is an array of address information where fields are `ip`, `family`, `netmask`, `internal`, and `mac`. **Returns:** `table` - `[name(s)]` : `table` - `ip` : `string` - `family` : `string` - `netmask` : `string` - `internal` : `boolean` - `mac` : `string` ### `uv.if_indextoname(ifindex)` **Parameters:** - `ifindex`: `integer` IPv6-capable implementation of `if_indextoname(3)`. **Returns:** `string` or `fail` ### `uv.if_indextoiid(ifindex)` **Parameters:** - `ifindex`: `integer` Retrieves a network interface identifier suitable for use in an IPv6 scoped address. On Windows, returns the numeric `ifindex` as a string. On all other platforms, `uv.if_indextoname()` is used. **Returns:** `string` or `fail` ### `uv.loadavg()` Returns the load average as a triad. Not supported on Windows. **Returns:** `number, number, number` ### `uv.os_uname()` Returns system information. **Returns:** `table` - `sysname` : `string` - `release` : `string` - `version` : `string` - `machine` : `string` ### `uv.os_gethostname()` Returns the hostname. **Returns:** `string` ### `uv.os_getenv(name, [size])` **Parameters:** - `name`: `string` - `size`: `integer` (default = `LUAL_BUFFERSIZE`) Returns the environment variable specified by `name` as string. The internal buffer size can be set by defining `size`. If omitted, `LUAL_BUFFERSIZE` is used. If the environment variable exceeds the storage available in the internal buffer, `ENOBUFS` is returned. If no matching environment variable exists, `ENOENT` is returned. **Returns:** `string` or `fail` **Warning:** This function is not thread safe. ### `uv.os_setenv(name, value)` **Parameters:** - `name`: `string` - `value`: `string` Sets the environmental variable specified by `name` with the string `value`. **Returns:** `boolean` or `fail` **Warning:** This function is not thread safe. ### `uv.os_unsetenv()` **Returns:** `boolean` or `fail` **Warning:** This function is not thread safe. ### `uv.os_environ()` Returns all environmental variables as a dynamic table of names associated with their corresponding values. **Returns:** `table` **Warning:** This function is not thread safe. ### `uv.os_homedir()` **Returns:** `string` or `fail` **Warning:** This function is not thread safe. ### `uv.os_tmpdir()` **Returns:** `string` or `fail` **Warning:** This function is not thread safe. ### `uv.os_get_passwd()` Returns password file information. **Returns:** `table` - `username` : `string` - `uid` : `integer` - `gid` : `integer` - `shell` : `string` - `homedir` : `string` ### `uv.os_getpid()` Returns the current process ID. **Returns:** `number` ### `uv.os_getppid()` Returns the parent process ID. **Returns:** `number` ### `uv.os_getpriority(pid)` **Parameters:** - `pid`: `integer` Returns the scheduling priority of the process specified by `pid`. **Returns:** `number` or `fail` ### `uv.os_setpriority(pid, priority)` **Parameters:** - `pid`: `integer` - `priority`: `integer` Sets the scheduling priority of the process specified by `pid`. The `priority` range is between -20 (high priority) and 19 (low priority). **Returns:** `boolean` or `fail` ### `uv.random(len, flags, [callback])` **Parameters:** - `len`: `integer` - `flags`: `nil` (see below) - `callback`: `callable` (async version) or `nil` (sync version) - `err`: `nil` or `string` - `bytes`: `string` or `nil` Fills a string of length `len` with cryptographically strong random bytes acquired from the system CSPRNG. `flags` is reserved for future extension and must currently be `nil` or `0` or `{}`. Short reads are not possible. When less than `len` random bytes are available, a non-zero error value is returned or passed to the callback. If the callback is omitted, this function is completed synchronously. The synchronous version may block indefinitely when not enough entropy is available. The asynchronous version may not ever finish when the system is low on entropy. **Returns (sync version):** `string` or `fail` **Returns (async version):** `0` or `fail` --- [luv]: https://github.com/luvit/luv [luvit]: https://github.com/luvit/luvit [libuv]: https://github.com/libuv/libuv [libuv documentation page]: http://docs.libuv.org/ [libuv API documentation]: http://docs.libuv.org/en/v1.x/api.html luv-1.36.0-0/examples/000077500000000000000000000000001364617304100143675ustar00rootroot00000000000000luv-1.36.0-0/examples/cqueues-main.lua000066400000000000000000000007541364617304100174740ustar00rootroot00000000000000--[[ Demonstrates using luv with a cqueues mainloop ]] local cqueues = require "cqueues" local uv = require "luv" local cq = cqueues.new() cq:wrap(function() while cqueues.poll({ pollfd = uv.backend_fd(); timeout = uv.backend_timeout() / 1000; events = "r"; }) do uv.run("nowait") end end) cq:wrap(function() while true do cqueues.sleep(1) print("HELLO FROM CQUEUES") end end) uv.new_timer():start(1000, 1000, function() print("HELLO FROM LUV") end) assert(cq:loop()) luv-1.36.0-0/examples/cqueues-slave.lua000066400000000000000000000026371364617304100176640ustar00rootroot00000000000000--[[ Demonstrates using cqueues with a luv mainloop Starts a simple sleep+print loop using each library's native form. They should print intertwined. ]] local cqueues = require "cqueues" local uv = require "luv" local cq = cqueues.new() do local timer = uv.new_timer() local function reset_timer() local timeout = cq:timeout() if timeout then -- libuv takes milliseconds as an integer, -- while cqueues gives timeouts as a floating point number -- use `math.ceil` as we'd rather wake up late than early timer:set_repeat(math.ceil(timeout * 1000)) timer:again() else -- stop timer for now; it may be restarted later. timer:stop() end end local function onready() -- Step the cqueues loop once (sleeping for max 0 seconds) assert(cq:step(0)) reset_timer() end -- Need to call `start` on libuv timer now -- to provide callback and so that `again` works timer:start(0, 0, onready) -- Ask libuv to watch the cqueue pollfd uv.new_poll(cq:pollfd()):start(cq:events(), onready) end -- Adds a new function to the scheduler `cq` -- The functions is an infinite loop that sleeps for 1 second and prints cq:wrap(function() while true do cqueues.sleep(1) print("HELLO FROM CQUEUES") end end) -- Start a luv timer that fires every 1 second uv.new_timer():start(1000, 1000, function() print("HELLO FROM LUV") end) -- Run luv mainloop uv.run() luv-1.36.0-0/examples/echo-server-client.lua000066400000000000000000000027341364617304100205760ustar00rootroot00000000000000local p = require('lib/utils').prettyPrint local uv = require('luv') local function create_server(host, port, on_connection) local server = uv.new_tcp() p(1, server) uv.tcp_bind(server, host, port) uv.listen(server, 128, function(err) assert(not err, err) local client = uv.new_tcp() uv.accept(server, client) on_connection(client) end) return server end local server = create_server("0.0.0.0", 0, function (client) p("new client", client, uv.tcp_getsockname(client), uv.tcp_getpeername(client)) uv.read_start(client, function (err, chunk) p("onread", {err=err,chunk=chunk}) -- Crash on errors assert(not err, err) if chunk then -- Echo anything heard uv.write(client, chunk) else -- When the stream ends, close the socket uv.close(client) end end) end) local address = uv.tcp_getsockname(server) p("server", server, address) local client = uv.new_tcp() uv.tcp_connect(client, "127.0.0.1", address.port, function (err) assert(not err, err) uv.read_start(client, function (err, chunk) p("received at client", {err=err,chunk=chunk}) assert(not err, err) if chunk then uv.shutdown(client) p("client done shutting down") else uv.close(client) uv.close(server) end end) p("writing from client") uv.write(client, "Hello") uv.write(client, "World") end) -- Start the main event loop uv.run() -- Close any stray handles when done uv.walk(uv.close) uv.run() luv-1.36.0-0/examples/killing-children.lua000066400000000000000000000006001364617304100203050ustar00rootroot00000000000000local p = require('lib/utils').prettyPrint local uv = require('luv') local child, pid child, pid = uv.spawn("sleep", { args = {"100"} }, function (code, signal) p("EXIT", {code=code,signal=signal}) uv.close(child) end) p{child=child, pid=pid} -- uv.kill(pid, "SIGTERM") uv.process_kill(child, "SIGTERM") repeat print("\ntick.") until uv.run('once') == 0 print("done") luv-1.36.0-0/examples/lots-o-dns.lua000066400000000000000000000014751364617304100171000ustar00rootroot00000000000000local p = require('lib/utils').prettyPrint local uv = require('luv') uv.getaddrinfo(nil, 80, nil, p) local domains = { "facebook.com", "google.com", "mail.google.com", "maps.google.com", "plus.google.com", "play.google.com", "apple.com", "hp.com", "yahoo.com", "mozilla.com", "developer.mozilla.com", "luvit.io", "creationix.com", "howtonode.org", "github.com", "gist.github.com" } local i = 1 local function next() uv.getaddrinfo(domains[i], nil, { v4mapped = true, all = true, addrconfig = true, canonname = true, numericserv = true, socktype = "STREAM" }, function (err, data) assert(not err, err) p(data) i = i + 1 if i <= #domains then next() end end) end next(); repeat print("\nTick..") until uv.run('once') == 0 print("done") luv-1.36.0-0/examples/repl.lua000066400000000000000000000033661364617304100160440ustar00rootroot00000000000000local uv = require('luv') local utils = require('lib/utils') if uv.guess_handle(0) ~= "tty" or uv.guess_handle(1) ~= "tty" then error "stdio must be a tty" end local stdin = uv.new_tty(0, true) local stdout = require('lib/utils').stdout local debug = require('debug') local c = utils.color local function gatherResults(success, ...) local n = select('#', ...) return success, { n = n, ... } end local function printResults(results) for i = 1, results.n do results[i] = utils.dump(results[i]) end print(table.concat(results, '\t')) end local buffer = '' local function evaluateLine(line) if line == "<3\n" then print("I " .. c("Bred") .. "♥" .. c() .. " you too!") return '>' end local chunk = buffer .. line local f, err = loadstring('return ' .. chunk, 'REPL') -- first we prefix return if not f then f, err = loadstring(chunk, 'REPL') -- try again without return end if f then buffer = '' local success, results = gatherResults(xpcall(f, debug.traceback)) if success then -- successful call if results.n > 0 then printResults(results) end else -- error print(results[1]) end else if err:match "''$" then -- Lua expects some more input; stow it away for next time buffer = chunk .. '\n' return '>>' else print(err) buffer = '' end end return '>' end local function displayPrompt(prompt) uv.write(stdout, prompt .. ' ') end local function onread(err, line) if err then error(err) end if line then local prompt = evaluateLine(line) displayPrompt(prompt) else uv.close(stdin) end end coroutine.wrap(function() displayPrompt '>' uv.read_start(stdin, onread) end)() uv.run() print("") luv-1.36.0-0/examples/talking-to-children.lua000066400000000000000000000014751364617304100207400ustar00rootroot00000000000000local p = require('lib/utils').prettyPrint local uv = require('luv') local stdout = uv.new_pipe(false) local stderr = uv.new_pipe( false) local stdin = uv.new_pipe(false) local handle, pid local function onexit(code, signal) p("exit", {code=code,signal=signal}) end local function onclose() p("close") end local function onread(err, chunk) assert(not err, err) if (chunk) then p("data", {data=chunk}) else p("end") end end local function onshutdown(err) if err == "ECANCELED" then return end uv.close(handle, onclose) end handle, pid = uv.spawn("cat", { stdio = {stdin, stdout, stderr} }, onexit) p{ handle=handle, pid=pid } uv.read_start(stdout, onread) uv.read_start(stderr, onread) uv.write(stdin, "Hello World") uv.shutdown(stdin, onshutdown) uv.run() uv.walk(uv.close) uv.run() luv-1.36.0-0/examples/tcp-cluster.lua000066400000000000000000000042761364617304100173500ustar00rootroot00000000000000 -- This function will be run in a child process local child_code = string.dump(function () local p = require('lib/utils').prettyPrint local uv = require('luv') -- The parent is going to pass us the server handle over a pipe -- This will be our local file descriptor at PIPE_FD local pipe = uv.new_pipe(true) local pipe_fd = tonumber(os.getenv("PIPE_FD")) assert(uv.pipe_open(pipe, pipe_fd)) -- Configure the server handle local server = uv.new_tcp() local function onconnection() local client = uv.new_tcp() uv.accept(server, client) p("New TCP", client, "on", server) p{client=client} uv.write(client, "BYE!\n"); uv.shutdown(client, function () uv.close(client) uv.close(server) end) end -- Read the server handle from the parent local function onread(err, data) p("onread", {err=err,data=data}) assert(not err, err) if uv.pipe_pending_count(pipe) > 0 then local pending_type = uv.pipe_pending_type(pipe) p("pending_type", pending_type) assert(pending_type == "tcp") assert(uv.accept(pipe, server)) assert(uv.listen(server, 128, onconnection)) p("Received server handle from parent process", server) elseif data then p("ondata", data) else p("onend", data) end end uv.read_start(pipe, onread) -- Start the event loop! uv.run() end) local p = require('lib/utils').prettyPrint local uv = require('luv') local exepath = assert(uv.exepath()) local cpu_count = # assert(uv.cpu_info()) local server = uv.new_tcp() assert(uv.tcp_bind(server, "::1", 1337)) print("Master process bound to TCP port 1337 on ::1") local function onexit(status, signal) p("Child exited", {status=status,signal=signal}) end local function spawnChild() local pipe = uv.new_pipe(true) local input = uv.new_pipe(false) local _, pid = assert(uv.spawn(exepath, { stdio = {input,1,2,pipe}, env= {"PIPE_FD=3"} }, onexit)) uv.write(input, child_code) uv.shutdown(input) p("Spawned child", pid, "and sending handle", server) assert(uv.write2(pipe, "123", server)) assert(uv.shutdown(pipe)) end -- Spawn a child process for each CPU core for _ = 1, cpu_count do spawnChild() end uv.run() luv-1.36.0-0/examples/timers.lua000066400000000000000000000023271364617304100164010ustar00rootroot00000000000000local p = require('lib/utils').prettyPrint local uv = require('luv') local function set_timeout(timeout, callback) local timer = uv.new_timer() local function ontimeout() p("ontimeout", timer) uv.timer_stop(timer) uv.close(timer) callback(timer) end uv.timer_start(timer, timeout, 0, ontimeout) return timer end local function clear_timeout(timer) uv.timer_stop(timer) uv.close(timer) end local function set_interval(interval, callback) local timer = uv.new_timer() local function ontimeout() p("interval", timer) callback(timer) end uv.timer_start(timer, interval, interval, ontimeout) return timer end local clear_interval = clear_timeout local i = set_interval(300, function() print("interval...") end) set_timeout(1000, function() clear_interval(i) end) local handle = uv.new_timer() local delay = 1024 local function ontimeout() p("tick", delay) delay = delay / 2 if delay >= 1 then uv.timer_set_repeat(handle, delay) uv.timer_again(handle) else uv.timer_stop(handle) uv.close(handle) p("done") end end uv.timer_start(handle, delay, 0, ontimeout) repeat print("\ntick.") until uv.run('once') == 0 print("done") uv.walk(uv.close) uv.run() luv-1.36.0-0/examples/uvbook/000077500000000000000000000000001364617304100156745ustar00rootroot00000000000000luv-1.36.0-0/examples/uvbook/helloworld.lua000066400000000000000000000001041364617304100205450ustar00rootroot00000000000000local uv = require('luv') print('Now quitting.') uv.run('default') luv-1.36.0-0/examples/uvbook/idle-basic.lua000066400000000000000000000003321364617304100203710ustar00rootroot00000000000000local uv = require('luv') local counter = 0 local idle = uv.new_idle() idle:start(function() counter = counter + 1 if counter >= 10e6 then idle:stop() end end) print("Idling...") uv.run('default')luv-1.36.0-0/examples/uvbook/onchange.lua000066400000000000000000000012521364617304100201610ustar00rootroot00000000000000local uv = require('luv') if #arg==0 then print(string.format("Usage: %s [file2 ...]",arg[0])); return end for i=1,#arg do local fse = uv.new_fs_event() assert(uv.fs_event_start(fse,arg[i],{ --"watch_entry"=true,"stat"=true, recursive=true },function (err,fname,status) if(err) then print("Error "..err) else print(string.format('Change detected in %s', uv.fs_event_getpath(fse))) for k,v in pairs(status) do print(k,v) end print('file changed:'..(fname and fname or '')) end end)) end uv.run('default') luv-1.36.0-0/examples/uvbook/pipe-echo-client.lua000066400000000000000000000006201364617304100215220ustar00rootroot00000000000000local uv = require("uv") local SOCK = "/tmp/echo.sock" local client = uv.new_pipe(false) client:connect(SOCK, function (err) assert(not err, err) client:read_start(function (err, chunk) assert(not err, err) if chunk then print(chunk) else client:close() end end) client:write("Hello ") client:write("world!") end) print("CTRL-C to break") uv.run("default") luv-1.36.0-0/examples/uvbook/pipe-echo-server.lua000066400000000000000000000013171364617304100215560ustar00rootroot00000000000000local uv = require("uv") local SOCK = "/tmp/echo.sock" local server = uv.new_pipe(false) local ret, err, code = server:bind(SOCK) -- if file already exists, remove it first and try again if not ret and code == "EADDRINUSE" then local fs = require("fs") fs.unlinkSync(SOCK) _, err, _ = server:bind(SOCK) assert(not err, err) else assert(not err, err) end server:listen(128, function (err) assert(not err, err) local client = uv.new_pipe(false) server:accept(client) client:read_start(function (err, chunk) assert(not err, err) if chunk then print("Got: " .. chunk) client:write(chunk) else client:shutdown() client:close() end end) end) uv.run("default") luv-1.36.0-0/examples/uvbook/queue-work.lua000066400000000000000000000006541364617304100205100ustar00rootroot00000000000000local uv = require('luv') local ctx = uv.new_work( function(n) --work,in threadpool local uv = require('luv') local t = uv.thread_self() uv.sleep(100) return n*n,n end, function(r,n) print(string.format('%d => %d',n,r)) end --after work, in loop thread ) uv.queue_work(ctx,2) uv.queue_work(ctx,4) uv.queue_work(ctx,6) uv.queue_work(ctx,8) uv.queue_work(ctx,10) uv.run('default') luv-1.36.0-0/examples/uvbook/tcp-echo-client.lua000066400000000000000000000006421364617304100213570ustar00rootroot00000000000000local uv = require('luv') local client = uv.new_tcp() uv.tcp_connect(client, "127.0.0.1", 1337, function (err) assert(not err, err) uv.read_start(client, function (err, chunk) assert(not err, err) if chunk then print(chunk) else uv.close(client) end end) uv.write(client, "Hello") uv.write(client, "World") end) print('CTRL-C to break') uv.run('default') luv-1.36.0-0/examples/uvbook/tcp-echo-server.lua000066400000000000000000000006221364617304100214050ustar00rootroot00000000000000local uv = require('luv') local server = uv.new_tcp() server:bind("127.0.0.1", 1337) server:listen(128, function (err) assert(not err, err) local client = uv.new_tcp() server:accept(client) client:read_start(function (err, chunk) assert(not err, err) if chunk then client:write(chunk) else client:shutdown() client:close() end end) end) uv.run('default') luv-1.36.0-0/examples/uvbook/thread-create.lua000066400000000000000000000017731364617304100211170ustar00rootroot00000000000000local uv = require('luv') local step = 10 local hare_id = uv.new_thread(function(step,...) local ffi = require'ffi' local uv = require('luv') local sleep if ffi.os=='Windows' then ffi.cdef "void Sleep(int ms);" sleep = ffi.C.Sleep else ffi.cdef "unsigned int usleep(unsigned int seconds);" sleep = ffi.C.usleep end while (step>0) do step = step - 1 sleep(math.random(1000)) print("Hare ran another step") end print("Hare done running!") end, step,true,'abcd','false') local tortoise_id = uv.new_thread(function(step,...) local uv = require('luv') while (step>0) do step = step - 1 uv.sleep(math.random(100)) print("Tortoise ran another step") end print("Tortoise done running!") end,step,'abcd','false') print(hare_id==hare_id,uv.thread_equal(hare_id,hare_id)) print(tortoise_id==hare_id,uv.thread_equal(tortoise_id,hare_id)) uv.thread_join(hare_id) uv.thread_join(tortoise_id) luv-1.36.0-0/examples/uvbook/uvcat.lua000066400000000000000000000015721364617304100175260ustar00rootroot00000000000000local uv = require('luv') local fname = arg[1] and arg[1] or arg[0] uv.fs_open(fname, 'r', tonumber('644', 8), function(err,fd) if err then print("error opening file:"..err) else local stat = uv.fs_fstat(fd) local off = 0 local block = 10 local function on_read(err,chunk) if(err) then print("Read error: "..err); elseif #chunk==0 then uv.fs_close(fd) else off = block + off uv.fs_write(1,chunk,-1,function(err,chunk) if err then print("Write error: "..err) else uv.fs_read(fd, block, off, on_read) end end) end end uv.fs_read(fd, block, off, on_read) end end) uv.run('default') luv-1.36.0-0/examples/uvbook/uvtee.lua000066400000000000000000000013641364617304100175330ustar00rootroot00000000000000local uv = require('luv') if not arg[1] then print(string.format("please run %s filename",arg[0])) return end local stdin = uv.new_tty(0, true) local stdout = uv.new_tty(1, true) --local stdin_pipe = uv.new_pipe(false) --uv.pipe_open(stdin_pipe,0) local fname = arg[1] uv.fs_open(fname, 'w+', tonumber('644', 8), function(err,fd) if err then print("error opening file:"..err) else local fpipe = uv.new_pipe(false) uv.pipe_open(fpipe, fd) uv.read_start(stdin, function(err,chunk) if err then print('Read error: '..err) else uv.write(stdout,chunk) uv.write(fpipe,chunk) end end); end end) uv.run('default') luv-1.36.0-0/lgtm.yml000066400000000000000000000000501364617304100142320ustar00rootroot00000000000000path_classifiers: library: - deps luv-1.36.0-0/lib/000077500000000000000000000000001364617304100133175ustar00rootroot00000000000000luv-1.36.0-0/lib/tap.lua000066400000000000000000000101151364617304100146040ustar00rootroot00000000000000local uv = require('luv') local dump = require('lib/utils').dump local stdout = require('lib/utils').stdout local uvVersionGEQ = require('lib/utils').uvVersionGEQ local function protect(...) local n = select('#', ...) local arguments = {...} for i = 1, n do arguments[i] = tostring(arguments[i]) end local text = table.concat(arguments, "\t") text = " " .. string.gsub(text, "\n", "\n ") print(text) end local function pprotect(...) local n = select('#', ...) local arguments = { ... } for i = 1, n do arguments[i] = dump(arguments[i]) end protect(table.concat(arguments, "\t")) end local tests = {}; local function run() local passed = 0 local skipped = 0 if #tests < 1 then error("No tests specified!") end print("1.." .. #tests) for i = 1, #tests do local test = tests[i] if not uvVersionGEQ(test.min_uv_ver) then print("ok " .. i .. " " .. test.name .. " # skip Requires libuv >= " .. test.min_uv_ver) skipped = skipped + 1 else local cwd = uv.cwd() local pass, err = xpcall(function () local expected = 0 local function expect(fn, count) expected = expected + (count or 1) return function (...) expected = expected - 1 local ret = fn(...) collectgarbage() return ret end end test.fn(protect, pprotect, expect, uv) collectgarbage() uv.run() collectgarbage() if expected > 0 then error("Missing " .. expected .. " expected call" .. (expected == 1 and "" or "s")) elseif expected < 0 then error("Found " .. -expected .. " unexpected call" .. (expected == -1 and "" or "s")) end collectgarbage() local unclosed = 0 uv.walk(function (handle) if handle == stdout then return end unclosed = unclosed + 1 print("UNCLOSED", handle) end) if unclosed > 0 then error(unclosed .. " unclosed handle" .. (unclosed == 1 and "" or "s")) end if uv.cwd() ~= cwd then error("Test moved cwd from " .. cwd .. " to " .. uv.cwd()) end collectgarbage() end, debug.traceback) -- Flush out any more opened handles uv.stop() uv.walk(function (handle) if handle == stdout then return end if not uv.is_closing(handle) then uv.close(handle) end end) uv.run() uv.chdir(cwd) if pass then print("ok " .. i .. " " .. test.name) passed = passed + 1 else protect(err) print("not ok " .. i .. " " .. test.name) end end end local failed = #tests - passed - skipped if failed == 0 then print("# All tests passed" .. (skipped > 0 and (" ("..skipped.." skipped)") or "")) else print("#" .. failed .. " failed test" .. (failed == 1 and "" or "s")) end -- Close all then handles, including stdout uv.walk(uv.close) uv.run() if failed ~= 0 then os.exit(-failed, true) end end local single = true local prefix local function tap(suite) if type(suite) == "function" then -- Pass in suite directly for single mode suite(function (name, fn, min_uv_ver) if prefix then name = prefix .. ' - ' .. name end tests[#tests + 1] = { name = name, fn = fn, min_uv_ver = min_uv_ver, } end) prefix = nil elseif type(suite) == "string" then prefix = suite single = false else -- Or pass in false to collect several runs of tests -- And then pass in true in a later call to flush tests queue. single = suite end if single then run() end end --[[ -- Sample Usage local passed, failed, total = tap(function (test) test("add 1 to 2", function(print) print("Adding 1 to 2") assert(1 + 2 == 3) end) test("close handle", function (print, p, expect, uv) local handle = uv.new_timer() uv.close(handle, expect(function (self) assert(self == handle) end)) end) test("simulate failure", function () error("Oopsie!") end) end) ]] return tap luv-1.36.0-0/lib/utils.lua000066400000000000000000000112761364617304100151710ustar00rootroot00000000000000 local uv = require('luv') local utils = {} local usecolors if uv.guess_handle(1) == "tty" then utils.stdout = uv.new_tty(1, false) usecolors = true else utils.stdout = uv.new_pipe(false) uv.pipe_open(utils.stdout, 1) usecolors = false end if _G.jit and _G.jit.os then -- Luajit provides explicit platform detection utils.isWindows = _G.jit.os == "Windows" else -- Normal lua will only have \ for path separator on windows. utils.isWindows = package.config:find("\\") and true or false end local colors = { black = "0;30", red = "0;31", green = "0;32", yellow = "0;33", blue = "0;34", magenta = "0;35", cyan = "0;36", white = "0;37", B = "1;", Bblack = "1;30", Bred = "1;31", Bgreen = "1;32", Byellow = "1;33", Bblue = "1;34", Bmagenta = "1;35", Bcyan = "1;36", Bwhite = "1;37" } function utils.color(color_name) if usecolors then return "\27[" .. (colors[color_name] or "0") .. "m" else return "" end end function utils.colorize(color_name, string, reset_name) return utils.color(color_name) .. tostring(string) .. utils.color(reset_name) end local backslash, null, newline, carriage, tab, quote, quote2, obracket, cbracket function utils.loadColors(n) if n ~= nil then usecolors = n end backslash = utils.colorize("Bgreen", "\\\\", "green") null = utils.colorize("Bgreen", "\\0", "green") newline = utils.colorize("Bgreen", "\\n", "green") carriage = utils.colorize("Bgreen", "\\r", "green") tab = utils.colorize("Bgreen", "\\t", "green") quote = utils.colorize("Bgreen", '"', "green") quote2 = utils.colorize("Bgreen", '"') obracket = utils.colorize("B", '[') cbracket = utils.colorize("B", ']') end utils.loadColors() function utils.dump(o, depth) local t = type(o) if t == 'string' then return quote .. o:gsub("\\", backslash):gsub("%z", null):gsub("\n", newline):gsub("\r", carriage):gsub("\t", tab) .. quote2 end if t == 'nil' then return utils.colorize("Bblack", "nil") end if t == 'boolean' then return utils.colorize("yellow", tostring(o)) end if t == 'number' then return utils.colorize("blue", tostring(o)) end if t == 'userdata' then return utils.colorize("magenta", tostring(o)) end if t == 'thread' then return utils.colorize("Bred", tostring(o)) end if t == 'function' then return utils.colorize("cyan", tostring(o)) end if t == 'cdata' then return utils.colorize("Bmagenta", tostring(o)) end if t == 'table' then if type(depth) == 'nil' then depth = 0 end if depth > 1 then return utils.colorize("yellow", tostring(o)) end local indent = (" "):rep(depth) -- Check to see if this is an array local is_array = true local i = 1 for k,v in pairs(o) do if not (k == i) then is_array = false end i = i + 1 end local first = true local lines = {} i = 1 local estimated = 0 for k,v in (is_array and ipairs or pairs)(o) do local s if is_array then s = "" else if type(k) == "string" and k:find("^[%a_][%a%d_]*$") then s = k .. ' = ' else s = '[' .. utils.dump(k, 100) .. '] = ' end end s = s .. utils.dump(v, depth + 1) lines[i] = s estimated = estimated + #s i = i + 1 end if estimated > 200 then return "{\n " .. indent .. table.concat(lines, ",\n " .. indent) .. "\n" .. indent .. "}" else return "{ " .. table.concat(lines, ", ") .. " }" end end -- This doesn't happen right? return tostring(o) end -- Print replacement that goes through libuv. This is useful on windows -- to use libuv's code to translate ansi escape codes to windows API calls. function print(...) local n = select('#', ...) local arguments = {...} for i = 1, n do arguments[i] = tostring(arguments[i]) end uv.write(utils.stdout, table.concat(arguments, "\t") .. "\n") end -- A nice global data dumper function utils.prettyPrint(...) local n = select('#', ...) local arguments = { ... } for i = 1, n do arguments[i] = utils.dump(arguments[i]) end print(table.concat(arguments, "\t")) end function utils.uvVersionGEQ(min_version) if not min_version then return true end local min_version_num = min_version if type(min_version) == "string" then local version_parts = {} for part in min_version:gmatch("%d+") do table.insert(version_parts, tonumber(part)) end assert(#version_parts == 3, "malformed version string: " .. min_version) min_version_num = version_parts[1]*0x10000 + version_parts[2]*0x100 + version_parts[3] end return uv.version() >= min_version_num end return utils luv-1.36.0-0/libluv.pc.in000066400000000000000000000004071364617304100150000ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=${prefix} libdir=@libdir@ includedir=@includedir@ Name: libluv Version: @LUV_VERSION@ Description: Bare and full libuv bindings for Lua/LuaJIT. URL: https://github.com/luvit/luv Libs: -L${libdir} -lluv @LIBS@ Cflags: -I${includedir} luv-1.36.0-0/luv-scm-0.rockspec000066400000000000000000000013211364617304100160240ustar00rootroot00000000000000package = "luv" version = "scm-0" source = { url = 'git://github.com/luvit/luv.git' } description = { summary = "Bare libuv bindings for lua", detailed = [[ libuv bindings for luajit and lua 5.1/5.2/5.3. This library makes libuv available to lua scripts. It was made for the luvit project but should usable from nearly any lua project. ]], homepage = "https://github.com/luvit/luv", license = "Apache 2.0" } dependencies = { "lua >= 5.1" } build = { type = 'cmake', variables = { CMAKE_C_FLAGS="$(CFLAGS)", CMAKE_MODULE_LINKER_FLAGS="$(LIBFLAG)", LUA_LIBDIR="$(LUA_LIBDIR)", LUA_INCDIR="$(LUA_INCDIR)", LUA="$(LUA)", LIBDIR="$(LIBDIR)", LUADIR="$(LUADIR)", }, } luv-1.36.0-0/msvcbuild.bat000066400000000000000000000013751364617304100152370ustar00rootroot00000000000000@echo off Setlocal EnableDelayedExpansion if not defined VS set VS=15 if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" (set VS=16) if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (set VS=15) if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (set VS=14) if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" (set VS=12) set ARCH= if %VS% LEQ 15 ( if not defined platform set platform=x64 if "!platform!" EQU "x64" (set VS=%VS% Win64) ) else ( :: If -A is not specified, defaults to host arch if "%platform%" EQU "x86" (set ARCH= -A Win32) if "%platform%" EQU "x64" (set ARCH= -A x64) ) cmake -H. -Bbuild -G"Visual Studio %VS%"%ARCH% cmake --build build --config Release copy build\Release\luv.dll . copy build\Release\luajit.exe . luv-1.36.0-0/rockspecs/000077500000000000000000000000001364617304100145455ustar00rootroot00000000000000luv-1.36.0-0/rockspecs/luv-scm-0.rockspec000066400000000000000000000031201364617304100200170ustar00rootroot00000000000000-- Alternate rockspec that uses luarocks builtin builder package = "luv" version = "scm-0" source = { url = 'git://github.com/luvit/luv.git' } description = { summary = "Bare libuv bindings for lua", detailed = [[ libuv bindings for luajit and lua 5.1/5.2/5.3. This library makes libuv available to lua scripts. It was made for the luvit project but should usable from nearly any lua project. ]], homepage = "https://github.com/luvit/luv", license = "Apache 2.0" } dependencies = { "lua >= 5.1" } external_dependencies = { LIBUV = { header = 'uv.h', library = 'uv', }, LUA_COMPAT53 = { header = "compat-5.3.h" } } build = { type = 'builtin', -- default (platform-agnostic) configuration modules = { ['luv'] = { sources = {'src/luv.c'}, libraries = {'uv'}, incdirs = {"$(LIBUV_INCDIR)","$(LUA_COMPAT53_INCDIR)"}, libdirs = {"$(LIBUV_LIBDIR)"} } }; -- per-platform overrides platforms = { linux = { modules = { ['luv'] = { libraries = { nil; 'pthread'; 'rt'; 'dl'; }; }; }; }; freebsd = { modules = { ['luv'] = { libraries = { nil; 'pthread'; 'kvm'; }; }; }; }; windows = { modules = { ['luv'] = { libraries = { nil; 'User32'; 'psapi'; 'iphlpapi'; 'userenv'; 'ws2_32'; 'advapi32'; }; }; }; }; } } luv-1.36.0-0/src/000077500000000000000000000000001364617304100133405ustar00rootroot00000000000000luv-1.36.0-0/src/async.c000066400000000000000000000043701364617304100146250ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_async_t* luv_check_async(lua_State* L, int index) { uv_async_t* handle = (uv_async_t*)luv_checkudata(L, index, "uv_async"); luaL_argcheck(L, handle->type == UV_ASYNC && handle->data, index, "Expected uv_async_t"); return handle; } static void luv_async_cb(uv_async_t* handle) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; int n = luv_thread_arg_push(L, (luv_thread_arg_t*)data->extra, LUVF_THREAD_SIDE_MAIN); luv_call_callback(L, data, LUV_ASYNC, n); luv_thread_arg_clear(L, (luv_thread_arg_t*)data->extra, LUVF_THREAD_SIDE_MAIN); } static int luv_new_async(lua_State* L) { uv_async_t* handle; luv_handle_t* data; int ret; luv_ctx_t* ctx = luv_context(L); luaL_checktype(L, 1, LUA_TFUNCTION); handle = (uv_async_t*)luv_newuserdata(L, sizeof(*handle)); ret = uv_async_init(ctx->loop, handle, luv_async_cb); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } data = luv_setup_handle(L, ctx); data->extra = (luv_thread_arg_t*)malloc(sizeof(luv_thread_arg_t)); data->extra_gc = free; memset(data->extra, 0, sizeof(luv_thread_arg_t)); handle->data = data; luv_check_callback(L, (luv_handle_t*)handle->data, LUV_ASYNC, 1); return 1; } static int luv_async_send(lua_State* L) { int ret; uv_async_t* handle = luv_check_async(L, 1); luv_thread_arg_t* arg = (luv_thread_arg_t *)((luv_handle_t*) handle->data)->extra; luv_thread_arg_set(L, arg, 2, lua_gettop(L), LUVF_THREAD_MODE_ASYNC|LUVF_THREAD_SIDE_CHILD); ret = uv_async_send(handle); luv_thread_arg_clear(L, arg, LUVF_THREAD_SIDE_CHILD); return luv_result(L, ret); } luv-1.36.0-0/src/check.c000066400000000000000000000034201364617304100145600ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_check_t* luv_check_check(lua_State* L, int index) { uv_check_t* handle = (uv_check_t*)luv_checkudata(L, index, "uv_check"); luaL_argcheck(L, handle->type == UV_CHECK && handle->data, index, "Expected uv_check_t"); return handle; } static int luv_new_check(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_check_t* handle = (uv_check_t*)luv_newuserdata(L, sizeof(*handle)); int ret = uv_check_init(ctx->loop, handle); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static void luv_check_cb(uv_check_t* handle) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; luv_call_callback(L, data, LUV_CHECK, 0); } static int luv_check_start(lua_State* L) { uv_check_t* handle = luv_check_check(L, 1); int ret; luv_check_callback(L, (luv_handle_t *)handle->data, LUV_CHECK, 2); ret = uv_check_start(handle, luv_check_cb); return luv_result(L, ret); } static int luv_check_stop(lua_State* L) { uv_check_t* handle = luv_check_check(L, 1); int ret = uv_check_stop(handle); return luv_result(L, ret); } luv-1.36.0-0/src/constants.c000066400000000000000000000337161364617304100155320ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "luv.h" static int luv_constants(lua_State* L) { lua_newtable(L); // File open bitwise flags O_* #ifdef O_RDONLY lua_pushinteger(L, O_RDONLY); lua_setfield(L, -2, "O_RDONLY"); #endif #ifdef O_WRONLY lua_pushinteger(L, O_WRONLY); lua_setfield(L, -2, "O_WRONLY"); #endif #ifdef O_RDWR lua_pushinteger(L, O_RDWR); lua_setfield(L, -2, "O_RDWR"); #endif #ifdef O_APPEND lua_pushinteger(L, O_APPEND); lua_setfield(L, -2, "O_APPEND"); #endif #ifdef O_CREAT lua_pushinteger(L, O_CREAT); lua_setfield(L, -2, "O_CREAT"); #endif #ifdef O_DSYNC lua_pushinteger(L, O_DSYNC); lua_setfield(L, -2, "O_DSYNC"); #endif #ifdef O_EXCL lua_pushinteger(L, O_EXCL); lua_setfield(L, -2, "O_EXCL"); #endif #ifdef O_EXLOCK lua_pushinteger(L, O_EXLOCK); lua_setfield(L, -2, "O_EXLOCK"); #endif #ifdef O_NOCTTY lua_pushinteger(L, O_NOCTTY); lua_setfield(L, -2, "O_NOCTTY"); #endif #ifdef O_NONBLOCK lua_pushinteger(L, O_NONBLOCK); lua_setfield(L, -2, "O_NONBLOCK"); #endif #ifdef O_RSYNC lua_pushinteger(L, O_RSYNC); lua_setfield(L, -2, "O_RSYNC"); #endif #ifdef O_SYNC lua_pushinteger(L, O_SYNC); lua_setfield(L, -2, "O_SYNC"); #endif #ifdef O_TRUNC lua_pushinteger(L, O_TRUNC); lua_setfield(L, -2, "O_TRUNC"); #endif // Socket types SOCK_* #ifdef SOCK_STREAM lua_pushinteger(L, SOCK_STREAM); lua_setfield(L, -2, "SOCK_STREAM"); #endif #ifdef SOCK_DGRAM lua_pushinteger(L, SOCK_DGRAM); lua_setfield(L, -2, "SOCK_DGRAM"); #endif #ifdef SOCK_SEQPACKET lua_pushinteger(L, SOCK_SEQPACKET); lua_setfield(L, -2, "SOCK_SEQPACKET"); #endif #ifdef SOCK_RAW lua_pushinteger(L, SOCK_RAW); lua_setfield(L, -2, "SOCK_RAW"); #endif #ifdef SOCK_RDM lua_pushinteger(L, SOCK_RDM); lua_setfield(L, -2, "SOCK_RDM"); #endif // AF_* #ifdef AF_UNIX lua_pushinteger(L, AF_UNIX); lua_setfield(L, -2, "AF_UNIX"); #endif #ifdef AF_INET lua_pushinteger(L, AF_INET); lua_setfield(L, -2, "AF_INET"); #endif #ifdef AF_INET6 lua_pushinteger(L, AF_INET6); lua_setfield(L, -2, "AF_INET6"); #endif #ifdef AF_IPX lua_pushinteger(L, AF_IPX); lua_setfield(L, -2, "AF_IPX"); #endif #ifdef AF_NETLINK lua_pushinteger(L, AF_NETLINK); lua_setfield(L, -2, "AF_NETLINK"); #endif #ifdef AF_X25 lua_pushinteger(L, AF_X25); lua_setfield(L, -2, "AF_X25"); #endif #ifdef AF_AX25 lua_pushinteger(L, AF_AX25); lua_setfield(L, -2, "AF_AX25"); #endif #ifdef AF_ATMPVC lua_pushinteger(L, AF_ATMPVC); lua_setfield(L, -2, "AF_ATMPVC"); #endif #ifdef AF_APPLETALK lua_pushinteger(L, AF_APPLETALK); lua_setfield(L, -2, "AF_APPLETALK"); #endif #ifdef AF_PACKET lua_pushinteger(L, AF_PACKET); lua_setfield(L, -2, "AF_PACKET"); #endif // AI_* #ifdef AI_ADDRCONFIG lua_pushinteger(L, AI_ADDRCONFIG); lua_setfield(L, -2, "AI_ADDRCONFIG"); #endif #ifdef AI_V4MAPPED lua_pushinteger(L, AI_V4MAPPED); lua_setfield(L, -2, "AI_V4MAPPED"); #endif #ifdef AI_ALL lua_pushinteger(L, AI_ALL); lua_setfield(L, -2, "AI_ALL"); #endif #ifdef AI_NUMERICHOST lua_pushinteger(L, AI_NUMERICHOST); lua_setfield(L, -2, "AI_NUMERICHOST"); #endif #ifdef AI_PASSIVE lua_pushinteger(L, AI_PASSIVE); lua_setfield(L, -2, "AI_PASSIVE"); #endif #ifdef AI_NUMERICSERV lua_pushinteger(L, AI_NUMERICSERV); lua_setfield(L, -2, "AI_NUMERICSERV"); #endif // Signals #ifdef SIGHUP lua_pushinteger(L, SIGHUP); lua_setfield(L, -2, "SIGHUP"); #endif #ifdef SIGINT lua_pushinteger(L, SIGINT); lua_setfield(L, -2, "SIGINT"); #endif #ifdef SIGQUIT lua_pushinteger(L, SIGQUIT); lua_setfield(L, -2, "SIGQUIT"); #endif #ifdef SIGILL lua_pushinteger(L, SIGILL); lua_setfield(L, -2, "SIGILL"); #endif #ifdef SIGTRAP lua_pushinteger(L, SIGTRAP); lua_setfield(L, -2, "SIGTRAP"); #endif #ifdef SIGABRT lua_pushinteger(L, SIGABRT); lua_setfield(L, -2, "SIGABRT"); #endif #ifdef SIGIOT lua_pushinteger(L, SIGIOT); lua_setfield(L, -2, "SIGIOT"); #endif #ifdef SIGBUS lua_pushinteger(L, SIGBUS); lua_setfield(L, -2, "SIGBUS"); #endif #ifdef SIGFPE lua_pushinteger(L, SIGFPE); lua_setfield(L, -2, "SIGFPE"); #endif #ifdef SIGKILL lua_pushinteger(L, SIGKILL); lua_setfield(L, -2, "SIGKILL"); #endif #ifdef SIGUSR1 lua_pushinteger(L, SIGUSR1); lua_setfield(L, -2, "SIGUSR1"); #endif #ifdef SIGSEGV lua_pushinteger(L, SIGSEGV); lua_setfield(L, -2, "SIGSEGV"); #endif #ifdef SIGUSR2 lua_pushinteger(L, SIGUSR2); lua_setfield(L, -2, "SIGUSR2"); #endif #ifdef SIGPIPE lua_pushinteger(L, SIGPIPE); lua_setfield(L, -2, "SIGPIPE"); #endif #ifdef SIGALRM lua_pushinteger(L, SIGALRM); lua_setfield(L, -2, "SIGALRM"); #endif #ifdef SIGTERM lua_pushinteger(L, SIGTERM); lua_setfield(L, -2, "SIGTERM"); #endif #ifdef SIGCHLD lua_pushinteger(L, SIGCHLD); lua_setfield(L, -2, "SIGCHLD"); #endif #ifdef SIGSTKFLT lua_pushinteger(L, SIGSTKFLT); lua_setfield(L, -2, "SIGSTKFLT"); #endif #ifdef SIGCONT lua_pushinteger(L, SIGCONT); lua_setfield(L, -2, "SIGCONT"); #endif #ifdef SIGSTOP lua_pushinteger(L, SIGSTOP); lua_setfield(L, -2, "SIGSTOP"); #endif #ifdef SIGTSTP lua_pushinteger(L, SIGTSTP); lua_setfield(L, -2, "SIGTSTP"); #endif #ifdef SIGBREAK lua_pushinteger(L, SIGBREAK); lua_setfield(L, -2, "SIGBREAK"); #endif #ifdef SIGTTIN lua_pushinteger(L, SIGTTIN); lua_setfield(L, -2, "SIGTTIN"); #endif #ifdef SIGTTOU lua_pushinteger(L, SIGTTOU); lua_setfield(L, -2, "SIGTTOU"); #endif #ifdef SIGURG lua_pushinteger(L, SIGURG); lua_setfield(L, -2, "SIGURG"); #endif #ifdef SIGXCPU lua_pushinteger(L, SIGXCPU); lua_setfield(L, -2, "SIGXCPU"); #endif #ifdef SIGXFSZ lua_pushinteger(L, SIGXFSZ); lua_setfield(L, -2, "SIGXFSZ"); #endif #ifdef SIGVTALRM lua_pushinteger(L, SIGVTALRM); lua_setfield(L, -2, "SIGVTALRM"); #endif #ifdef SIGPROF lua_pushinteger(L, SIGPROF); lua_setfield(L, -2, "SIGPROF"); #endif #ifdef SIGWINCH lua_pushinteger(L, SIGWINCH); lua_setfield(L, -2, "SIGWINCH"); #endif #ifdef SIGIO lua_pushinteger(L, SIGIO); lua_setfield(L, -2, "SIGIO"); #endif #ifdef SIGPOLL lua_pushinteger(L, SIGPOLL); lua_setfield(L, -2, "SIGPOLL"); #endif #ifdef SIGLOST lua_pushinteger(L, SIGLOST); lua_setfield(L, -2, "SIGLOST"); #endif #ifdef SIGPWR lua_pushinteger(L, SIGPWR); lua_setfield(L, -2, "SIGPWR"); #endif #ifdef SIGSYS lua_pushinteger(L, SIGSYS); lua_setfield(L, -2, "SIGSYS"); #endif return 1; } static int luv_af_string_to_num(const char* string) { if (!string) return AF_UNSPEC; #ifdef AF_UNIX if (strcmp(string, "unix") == 0) return AF_UNIX; #endif #ifdef AF_INET if (strcmp(string, "inet") == 0) return AF_INET; #endif #ifdef AF_INET6 if (strcmp(string, "inet6") == 0) return AF_INET6; #endif #ifdef AF_IPX if (strcmp(string, "ipx") == 0) return AF_IPX; #endif #ifdef AF_NETLINK if (strcmp(string, "netlink") == 0) return AF_NETLINK; #endif #ifdef AF_X25 if (strcmp(string, "x25") == 0) return AF_X25; #endif #ifdef AF_AX25 if (strcmp(string, "ax25") == 0) return AF_AX25; #endif #ifdef AF_ATMPVC if (strcmp(string, "atmpvc") == 0) return AF_ATMPVC; #endif #ifdef AF_APPLETALK if (strcmp(string, "appletalk") == 0) return AF_APPLETALK; #endif #ifdef AF_PACKET if (strcmp(string, "packet") == 0) return AF_PACKET; #endif return 0; } static const char* luv_af_num_to_string(const int num) { switch (num) { #ifdef AF_UNIX case AF_UNIX: return "unix"; #endif #ifdef AF_INET case AF_INET: return "inet"; #endif #ifdef AF_INET6 case AF_INET6: return "inet6"; #endif #ifdef AF_IPX case AF_IPX: return "ipx"; #endif #ifdef AF_NETLINK case AF_NETLINK: return "netlink"; #endif #ifdef AF_X25 case AF_X25: return "x25"; #endif #ifdef AF_AX25 case AF_AX25: return "ax25"; #endif #ifdef AF_ATMPVC case AF_ATMPVC: return "atmpvc"; #endif #ifdef AF_APPLETALK case AF_APPLETALK: return "appletalk"; #endif #ifdef AF_PACKET case AF_PACKET: return "packet"; #endif } return NULL; } static int luv_sock_string_to_num(const char* string) { if (!string) return 0; #ifdef SOCK_STREAM if (strcmp(string, "stream") == 0) return SOCK_STREAM; #endif #ifdef SOCK_DGRAM if (strcmp(string, "dgram") == 0) return SOCK_DGRAM; #endif #ifdef SOCK_SEQPACKET if (strcmp(string, "seqpacket") == 0) return SOCK_SEQPACKET; #endif #ifdef SOCK_RAW if (strcmp(string, "raw") == 0) return SOCK_RAW; #endif #ifdef SOCK_RDM if (strcmp(string, "rdm") == 0) return SOCK_RDM; #endif return 0; } static const char* luv_sock_num_to_string(const int num) { switch (num) { #ifdef SOCK_STREAM case SOCK_STREAM: return "stream"; #endif #ifdef SOCK_DGRAM case SOCK_DGRAM: return "dgram"; #endif #ifdef SOCK_SEQPACKET case SOCK_SEQPACKET: return "seqpacket"; #endif #ifdef SOCK_RAW case SOCK_RAW: return "raw"; #endif #ifdef SOCK_RDM case SOCK_RDM: return "rdm"; #endif } return NULL; } static int luv_sig_string_to_num(const char* string) { if (!string) return 0; #ifdef SIGHUP if (strcmp(string, "sighup") == 0) return SIGHUP; #endif #ifdef SIGINT if (strcmp(string, "sigint") == 0) return SIGINT; #endif #ifdef SIGQUIT if (strcmp(string, "sigquit") == 0) return SIGQUIT; #endif #ifdef SIGILL if (strcmp(string, "sigill") == 0) return SIGILL; #endif #ifdef SIGTRAP if (strcmp(string, "sigtrap") == 0) return SIGTRAP; #endif #ifdef SIGABRT if (strcmp(string, "sigabrt") == 0) return SIGABRT; #endif #ifdef SIGIOT if (strcmp(string, "sigiot") == 0) return SIGIOT; #endif #ifdef SIGBUS if (strcmp(string, "sigbus") == 0) return SIGBUS; #endif #ifdef SIGFPE if (strcmp(string, "sigfpe") == 0) return SIGFPE; #endif #ifdef SIGKILL if (strcmp(string, "sigkill") == 0) return SIGKILL; #endif #ifdef SIGUSR1 if (strcmp(string, "sigusr1") == 0) return SIGUSR1; #endif #ifdef SIGSEGV if (strcmp(string, "sigsegv") == 0) return SIGSEGV; #endif #ifdef SIGUSR2 if (strcmp(string, "sigusr2") == 0) return SIGUSR2; #endif #ifdef SIGPIPE if (strcmp(string, "sigpipe") == 0) return SIGPIPE; #endif #ifdef SIGALRM if (strcmp(string, "sigalrm") == 0) return SIGALRM; #endif #ifdef SIGTERM if (strcmp(string, "sigterm") == 0) return SIGTERM; #endif #ifdef SIGCHLD if (strcmp(string, "sigchld") == 0) return SIGCHLD; #endif #ifdef SIGSTKFLT if (strcmp(string, "sigstkflt") == 0) return SIGSTKFLT; #endif #ifdef SIGCONT if (strcmp(string, "sigcont") == 0) return SIGCONT; #endif #ifdef SIGSTOP if (strcmp(string, "sigstop") == 0) return SIGSTOP; #endif #ifdef SIGTSTP if (strcmp(string, "sigtstp") == 0) return SIGTSTP; #endif #ifdef SIGBREAK if (strcmp(string, "sigbreak") == 0) return SIGBREAK; #endif #ifdef SIGTTIN if (strcmp(string, "sigttin") == 0) return SIGTTIN; #endif #ifdef SIGTTOU if (strcmp(string, "sigttou") == 0) return SIGTTOU; #endif #ifdef SIGURG if (strcmp(string, "sigurg") == 0) return SIGURG; #endif #ifdef SIGXCPU if (strcmp(string, "sigxcpu") == 0) return SIGXCPU; #endif #ifdef SIGXFSZ if (strcmp(string, "sigxfsz") == 0) return SIGXFSZ; #endif #ifdef SIGVTALRM if (strcmp(string, "sigvtalrm") == 0) return SIGVTALRM; #endif #ifdef SIGPROF if (strcmp(string, "sigprof") == 0) return SIGPROF; #endif #ifdef SIGWINCH if (strcmp(string, "sigwinch") == 0) return SIGWINCH; #endif #ifdef SIGIO if (strcmp(string, "sigio") == 0) return SIGIO; #endif #ifdef SIGPOLL if (strcmp(string, "sigpoll") == 0) return SIGPOLL; #endif #ifdef SIGLOST if (strcmp(string, "siglost") == 0) return SIGLOST; #endif #ifdef SIGPWR if (strcmp(string, "sigpwr") == 0) return SIGPWR; #endif #ifdef SIGSYS if (strcmp(string, "sigsys") == 0) return SIGSYS; #endif return 0; } static const char* luv_sig_num_to_string(const int num) { switch (num) { #ifdef SIGHUP case SIGHUP: return "sighup"; #endif #ifdef SIGINT case SIGINT: return "sigint"; #endif #ifdef SIGQUIT case SIGQUIT: return "sigquit"; #endif #ifdef SIGILL case SIGILL: return "sigill"; #endif #ifdef SIGTRAP case SIGTRAP: return "sigtrap"; #endif #ifdef SIGABRT case SIGABRT: return "sigabrt"; #endif #ifdef SIGIOT # if SIGIOT != SIGABRT case SIGIOT: return "sigiot"; # endif #endif #ifdef SIGBUS case SIGBUS: return "sigbus"; #endif #ifdef SIGFPE case SIGFPE: return "sigfpe"; #endif #ifdef SIGKILL case SIGKILL: return "sigkill"; #endif #ifdef SIGUSR1 case SIGUSR1: return "sigusr1"; #endif #ifdef SIGSEGV case SIGSEGV: return "sigsegv"; #endif #ifdef SIGUSR2 case SIGUSR2: return "sigusr2"; #endif #ifdef SIGPIPE case SIGPIPE: return "sigpipe"; #endif #ifdef SIGALRM case SIGALRM: return "sigalrm"; #endif #ifdef SIGTERM case SIGTERM: return "sigterm"; #endif #ifdef SIGCHLD case SIGCHLD: return "sigchld"; #endif #ifdef SIGSTKFLT case SIGSTKFLT: return "sigstkflt"; #endif #ifdef SIGCONT case SIGCONT: return "sigcont"; #endif #ifdef SIGSTOP case SIGSTOP: return "sigstop"; #endif #ifdef SIGTSTP case SIGTSTP: return "sigtstp"; #endif #ifdef SIGBREAK case SIGBREAK: return "sigbreak"; #endif #ifdef SIGTTIN case SIGTTIN: return "sigttin"; #endif #ifdef SIGTTOU case SIGTTOU: return "sigttou"; #endif #ifdef SIGURG case SIGURG: return "sigurg"; #endif #ifdef SIGXCPU case SIGXCPU: return "sigxcpu"; #endif #ifdef SIGXFSZ case SIGXFSZ: return "sigxfsz"; #endif #ifdef SIGVTALRM case SIGVTALRM: return "sigvtalrm"; #endif #ifdef SIGPROF case SIGPROF: return "sigprof"; #endif #ifdef SIGWINCH case SIGWINCH: return "sigwinch"; #endif #ifdef SIGIO case SIGIO: return "sigio"; #endif #ifdef SIGPOLL # if SIGPOLL != SIGIO case SIGPOLL: return "sigpoll"; # endif #endif #ifdef SIGLOST case SIGLOST: return "siglost"; #endif #ifdef SIGPWR # if SIGPWR != SIGLOST case SIGPWR: return "sigpwr"; # endif #endif #ifdef SIGSYS case SIGSYS: return "sigsys"; #endif } return NULL; } luv-1.36.0-0/src/dns.c000066400000000000000000000216101364617304100142700ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" #ifndef WIN32 #include #include #include #endif static void luv_pushaddrinfo(lua_State* L, struct addrinfo* res) { char ip[INET6_ADDRSTRLEN]; int port, i = 0; const char *addr; struct addrinfo* curr; lua_newtable(L); for (curr = res; curr; curr = curr->ai_next) { if (curr->ai_family == AF_INET || curr->ai_family == AF_INET6) { lua_newtable(L); if (curr->ai_family == AF_INET) { addr = (char*) &((struct sockaddr_in*) curr->ai_addr)->sin_addr; port = ((struct sockaddr_in*) curr->ai_addr)->sin_port; } else { addr = (char*) &((struct sockaddr_in6*) curr->ai_addr)->sin6_addr; port = ((struct sockaddr_in6*) curr->ai_addr)->sin6_port; } lua_pushstring(L, luv_af_num_to_string(curr->ai_family)); lua_setfield(L, -2, "family"); uv_inet_ntop(curr->ai_family, addr, ip, INET6_ADDRSTRLEN); lua_pushstring(L, ip); lua_setfield(L, -2, "addr"); if (ntohs(port)) { lua_pushinteger(L, ntohs(port)); lua_setfield(L, -2, "port"); } lua_pushstring(L, luv_sock_num_to_string(curr->ai_socktype)); lua_setfield(L, -2, "socktype"); lua_pushstring(L, luv_af_num_to_string(curr->ai_protocol)); lua_setfield(L, -2, "protocol"); if (curr->ai_canonname) { lua_pushstring(L, curr->ai_canonname); lua_setfield(L, -2, "canonname"); } lua_rawseti(L, -2, ++i); } } } static void luv_getaddrinfo_cb(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { luv_req_t* data = (luv_req_t*)req->data; lua_State* L = data->ctx->L; int nargs; if (status < 0) { luv_status(L, status); nargs = 1; } else { lua_pushnil(L); luv_pushaddrinfo(L, res); nargs = 2; } luv_fulfill_req(L, (luv_req_t*)req->data, nargs); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; if (res) uv_freeaddrinfo(res); } static int luv_getaddrinfo(lua_State* L) { uv_getaddrinfo_t* req; const char* node; const char* service; struct addrinfo hints_s; struct addrinfo* hints = &hints_s; int ret, ref; luv_ctx_t* ctx = luv_context(L); if (lua_isnoneornil(L, 1)) node = NULL; else node = luaL_checkstring(L, 1); if (lua_isnoneornil(L, 2)) service = NULL; else service = luaL_checkstring(L, 2); if (!lua_isnoneornil(L, 3)) luaL_checktype(L, 3, LUA_TTABLE); else hints = NULL; if (hints) { // Initialize the hints memset(hints, 0, sizeof(*hints)); // Process the `family` hint. lua_getfield(L, 3, "family"); if (lua_isnumber(L, -1)) { hints->ai_family = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { hints->ai_family = luv_af_string_to_num(lua_tostring(L, -1)); } else if (lua_isnil(L, -1)) { hints->ai_family = AF_UNSPEC; } else { luaL_argerror(L, 3, "family hint must be string if set"); } lua_pop(L, 1); // Process `socktype` hint lua_getfield(L, 3, "socktype"); if (lua_isnumber(L, -1)) { hints->ai_socktype = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { hints->ai_socktype = luv_sock_string_to_num(lua_tostring(L, -1)); } else if (!lua_isnil(L, -1)) { return luaL_argerror(L, 3, "socktype hint must be string if set"); } lua_pop(L, 1); // Process the `protocol` hint lua_getfield(L, 3, "protocol"); if (lua_isnumber(L, -1)) { hints->ai_protocol = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { int protocol = luv_af_string_to_num(lua_tostring(L, -1)); if (protocol) { hints->ai_protocol = protocol; } else { return luaL_argerror(L, 3, "Invalid protocol hint"); } } else if (!lua_isnil(L, -1)) { return luaL_argerror(L, 3, "protocol hint must be string if set"); } lua_pop(L, 1); lua_getfield(L, 3, "addrconfig"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_ADDRCONFIG; lua_pop(L, 1); #ifdef AI_V4MAPPED lua_getfield(L, 3, "v4mapped"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_V4MAPPED; lua_pop(L, 1); #endif #ifdef AI_ALL lua_getfield(L, 3, "all"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_ALL; lua_pop(L, 1); #endif lua_getfield(L, 3, "numerichost"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_NUMERICHOST; lua_pop(L, 1); lua_getfield(L, 3, "passive"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_PASSIVE; lua_pop(L, 1); lua_getfield(L, 3, "numericserv"); if (lua_toboolean(L, -1)) { hints->ai_flags |= AI_NUMERICSERV; /* On OS X upto at least OSX 10.9, getaddrinfo crashes * if AI_NUMERICSERV is set and the servname is NULL or "0". * This workaround avoids a segfault in libsystem. */ if (NULL == service) service = "00"; } lua_pop(L, 1); lua_getfield(L, 3, "canonname"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_CANONNAME; lua_pop(L, 1); } ref = luv_check_continuation(L, 4); #if !LUV_UV_VERSION_GEQ(1, 3, 0) // in libuv < 1.3.0, the callback cannot be NULL if (ref == LUA_NOREF) { return luaL_argerror(L, 4, "callback must be provided"); } #endif req = (uv_getaddrinfo_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); ret = uv_getaddrinfo(ctx->loop, req, ref == LUA_NOREF ? NULL : luv_getaddrinfo_cb, node, service, hints); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } #if LUV_UV_VERSION_GEQ(1, 3, 0) if (ref == LUA_NOREF) { lua_pop(L, 1); luv_pushaddrinfo(L, req->addrinfo); uv_freeaddrinfo(req->addrinfo); luv_cleanup_req(L, (luv_req_t*)req->data); } #endif return 1; } static void luv_getnameinfo_cb(uv_getnameinfo_t* req, int status, const char* hostname, const char* service) { luv_req_t* data = (luv_req_t*)req->data; lua_State* L = data->ctx->L; int nargs; if (status < 0) { luv_status(L, status); nargs = 1; } else { lua_pushnil(L); lua_pushstring(L, hostname); lua_pushstring(L, service); nargs = 3; } luv_fulfill_req(L, (luv_req_t*)req->data, nargs); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; } static int luv_getnameinfo(lua_State* L) { uv_getnameinfo_t* req; struct sockaddr_storage addr; const char* ip = NULL; int flags = 0; int ret, ref, port = 0; luv_ctx_t* ctx = luv_context(L); luaL_checktype(L, 1, LUA_TTABLE); memset(&addr, 0, sizeof(addr)); lua_getfield(L, 1, "ip"); if (lua_isstring(L, -1)) { ip = lua_tostring(L, -1); } else if (!lua_isnil(L, -1)) { luaL_argerror(L, 1, "ip property must be string if set"); } lua_pop(L, 1); lua_getfield(L, 1, "port"); if (lua_isnumber(L, -1)) { port = lua_tointeger(L, -1); } else if (!lua_isnil(L, -1)) { luaL_argerror(L, 1, "port property must be integer if set"); } lua_pop(L, 1); if (ip || port) { if (!ip) ip = "0.0.0.0"; if (!uv_ip4_addr(ip, port, (struct sockaddr_in*)&addr)) { addr.ss_family = AF_INET; } else if (!uv_ip6_addr(ip, port, (struct sockaddr_in6*)&addr)) { addr.ss_family = AF_INET6; } else { return luaL_argerror(L, 1, "Invalid ip address or port"); } } lua_getfield(L, 1, "family"); if (lua_isnumber(L, -1)) { addr.ss_family = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { addr.ss_family = luv_af_string_to_num(lua_tostring(L, -1)); } else if (!lua_isnil(L, -1)) { luaL_argerror(L, 1, "family must be string if set"); } lua_pop(L, 1); ref = luv_check_continuation(L, 2); #if !LUV_UV_VERSION_GEQ(1, 3, 0) // in libuv < 1.3.0, the callback cannot be NULL if (ref == LUA_NOREF) { return luaL_argerror(L, 2, "callback must be provided"); } #endif req = (uv_getnameinfo_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); ret = uv_getnameinfo(ctx->loop, req, ref == LUA_NOREF ? NULL : luv_getnameinfo_cb, (struct sockaddr*)&addr, flags); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } if (ref == LUA_NOREF) { lua_pop(L, 1); lua_pushstring(L, req->host); lua_pushstring(L, req->service); luv_cleanup_req(L, (luv_req_t*)req->data); return 2; } return 1; } luv-1.36.0-0/src/fs.c000066400000000000000000000674201364617304100141250ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_fs_t* luv_check_fs(lua_State* L, int index) { uv_fs_t* req = (uv_fs_t*)luaL_checkudata(L, index, "uv_req"); luaL_argcheck(L, req->type = (uv_req_type)(UV_FS && req->data), index, "Expected uv_fs_t"); return req; } static void luv_push_timespec_table(lua_State* L, const uv_timespec_t* t) { lua_createtable(L, 0, 2); lua_pushinteger(L, t->tv_sec); lua_setfield(L, -2, "sec"); lua_pushinteger(L, t->tv_nsec); lua_setfield(L, -2, "nsec"); } static void luv_push_stats_table(lua_State* L, const uv_stat_t* s) { const char* type = NULL; lua_createtable(L, 0, 23); lua_pushinteger(L, s->st_dev); lua_setfield(L, -2, "dev"); lua_pushinteger(L, s->st_mode); lua_setfield(L, -2, "mode"); lua_pushinteger(L, s->st_nlink); lua_setfield(L, -2, "nlink"); lua_pushinteger(L, s->st_uid); lua_setfield(L, -2, "uid"); lua_pushinteger(L, s->st_gid); lua_setfield(L, -2, "gid"); lua_pushinteger(L, s->st_rdev); lua_setfield(L, -2, "rdev"); lua_pushinteger(L, s->st_ino); lua_setfield(L, -2, "ino"); lua_pushinteger(L, s->st_size); lua_setfield(L, -2, "size"); lua_pushinteger(L, s->st_blksize); lua_setfield(L, -2, "blksize"); lua_pushinteger(L, s->st_blocks); lua_setfield(L, -2, "blocks"); lua_pushinteger(L, s->st_flags); lua_setfield(L, -2, "flags"); lua_pushinteger(L, s->st_gen); lua_setfield(L, -2, "gen"); luv_push_timespec_table(L, &s->st_atim); lua_setfield(L, -2, "atime"); luv_push_timespec_table(L, &s->st_mtim); lua_setfield(L, -2, "mtime"); luv_push_timespec_table(L, &s->st_ctim); lua_setfield(L, -2, "ctime"); luv_push_timespec_table(L, &s->st_birthtim); lua_setfield(L, -2, "birthtime"); if (S_ISREG(s->st_mode)) { type = "file"; } else if (S_ISDIR(s->st_mode)) { type = "directory"; } else if (S_ISLNK(s->st_mode)) { type = "link"; } else if (S_ISFIFO(s->st_mode)) { type = "fifo"; } #ifdef S_ISSOCK else if (S_ISSOCK(s->st_mode)) { type = "socket"; } #endif else if (S_ISCHR(s->st_mode)) { type = "char"; } else if (S_ISBLK(s->st_mode)) { type = "block"; } if (type) { lua_pushstring(L, type); lua_setfield(L, -2, "type"); } } static int luv_push_dirent(lua_State* L, const uv_dirent_t* ent, int table) { const char* type; if (table) { lua_newtable(L); } lua_pushstring(L, ent->name); if (table) { lua_setfield(L, -2, "name"); } switch (ent->type) { case UV_DIRENT_UNKNOWN: return 1; case UV_DIRENT_FILE: type = "file"; break; case UV_DIRENT_DIR: type = "directory"; break; case UV_DIRENT_LINK: type = "link"; break; case UV_DIRENT_FIFO: type = "fifo"; break; case UV_DIRENT_SOCKET: type = "socket"; break; case UV_DIRENT_CHAR: type = "char"; break; case UV_DIRENT_BLOCK: type = "block"; break; default: type = "unknown"; break; } lua_pushstring(L, type); if (table) lua_setfield(L, -2, "type"); return table ? 1 : 2; } static int luv_check_flags(lua_State* L, int index) { const char* string; if (lua_isnumber(L, index)) { return lua_tointeger(L, index); } else if (!lua_isstring(L, index)) { return luaL_argerror(L, index, "Expected string or integer for file open mode"); } string = lua_tostring(L, index); if (strcmp(string, "r") == 0) return O_RDONLY; #ifdef O_SYNC if (strcmp(string, "rs") == 0 || strcmp(string, "sr") == 0) return O_RDONLY | O_SYNC; #endif if (strcmp(string, "r+") == 0) return O_RDWR; #ifdef O_SYNC if (strcmp(string, "rs+") == 0 || strcmp(string, "sr+") == 0) return O_RDWR | O_SYNC; #endif if (strcmp(string, "w") == 0) return O_TRUNC | O_CREAT | O_WRONLY; if (strcmp(string, "wx") == 0 || strcmp(string, "xw") == 0) return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL; if (strcmp(string, "w+") == 0) return O_TRUNC | O_CREAT | O_RDWR; if (strcmp(string, "wx+") == 0 || strcmp(string, "xw+") == 0) return O_TRUNC | O_CREAT | O_RDWR | O_EXCL; if (strcmp(string, "a") == 0) return O_APPEND | O_CREAT | O_WRONLY; if (strcmp(string, "ax") == 0 || strcmp(string, "xa") == 0) return O_APPEND | O_CREAT | O_WRONLY | O_EXCL; if (strcmp(string, "a+") == 0) return O_APPEND | O_CREAT | O_RDWR; if (strcmp(string, "ax+") == 0 || strcmp(string, "xa+") == 0) return O_APPEND | O_CREAT | O_RDWR | O_EXCL; return luaL_error(L, "Unknown file open flag '%s'", string); } static int luv_check_amode(lua_State* L, int index) { size_t i; int mode; const char* string; if (lua_isnumber(L, index)) { return lua_tointeger(L, index); } else if (!lua_isstring(L, index)) { return luaL_argerror(L, index, "Expected string or integer for file access mode check"); } string = lua_tostring(L, index); mode = 0; for (i = 0; i < strlen(string); ++i) { switch (string[i]) { case 'r': case 'R': mode |= R_OK; break; case 'w': case 'W': mode |= W_OK; break; case 'x': case 'X': mode |= X_OK; break; default: return luaL_argerror(L, index, "Unknown character in access mode string"); } } return mode; } #if LUV_UV_VERSION_GEQ(1, 31, 0) static void luv_push_statfs_table(lua_State* L, const uv_statfs_t* s) { lua_createtable(L, 0, 8); lua_pushinteger(L, s->f_type); lua_setfield(L, -2, "type"); lua_pushinteger(L, s->f_bsize); lua_setfield(L, -2, "bsize"); lua_pushinteger(L, s->f_blocks); lua_setfield(L, -2, "blocks"); lua_pushinteger(L, s->f_bfree); lua_setfield(L, -2, "bfree"); lua_pushinteger(L, s->f_bavail); lua_setfield(L, -2, "bavail"); lua_pushinteger(L, s->f_files); lua_setfield(L, -2, "files"); lua_pushinteger(L, s->f_ffree); lua_setfield(L, -2, "ffree"); }; #endif /* Processes a result and pushes the data onto the stack returns the number of items pushed */ static int push_fs_result(lua_State* L, uv_fs_t* req) { luv_req_t* data = (luv_req_t*)req->data; if (req->fs_type == UV_FS_ACCESS) { lua_pushboolean(L, req->result >= 0); return 1; } if (req->result < 0) { lua_pushnil(L); if (req->path) { lua_pushfstring(L, "%s: %s: %s", uv_err_name(req->result), uv_strerror(req->result), req->path); } else { lua_pushfstring(L, "%s: %s", uv_err_name(req->result), uv_strerror(req->result)); } return 2; } switch (req->fs_type) { case UV_FS_CLOSE: case UV_FS_RENAME: case UV_FS_UNLINK: case UV_FS_RMDIR: case UV_FS_MKDIR: case UV_FS_FTRUNCATE: case UV_FS_FSYNC: case UV_FS_FDATASYNC: case UV_FS_LINK: case UV_FS_SYMLINK: case UV_FS_CHMOD: case UV_FS_FCHMOD: case UV_FS_CHOWN: case UV_FS_FCHOWN: #if LUV_UV_VERSION_GEQ(1, 21, 0) case UV_FS_LCHOWN: #endif case UV_FS_UTIME: case UV_FS_FUTIME: #if LUV_UV_VERSION_GEQ(1, 36, 0) case UV_FS_LUTIME: #endif #if LUV_UV_VERSION_GEQ(1, 14, 0) case UV_FS_COPYFILE: #endif lua_pushboolean(L, 1); return 1; case UV_FS_OPEN: case UV_FS_SENDFILE: case UV_FS_WRITE: lua_pushinteger(L, req->result); return 1; case UV_FS_STAT: case UV_FS_LSTAT: case UV_FS_FSTAT: luv_push_stats_table(L, &req->statbuf); return 1; #if LUV_UV_VERSION_GEQ(1, 31, 0) case UV_FS_STATFS: luv_push_statfs_table(L, req->ptr); return 1; #endif case UV_FS_MKDTEMP: lua_pushstring(L, req->path); return 1; #if LUV_UV_VERSION_GEQ(1, 34, 0) case UV_FS_MKSTEMP: lua_pushinteger(L, req->result); lua_pushstring(L, req->path); return 2; #endif case UV_FS_READLINK: #if LUV_UV_VERSION_GEQ(1, 8, 0) case UV_FS_REALPATH: #endif lua_pushstring(L, (char*)req->ptr); return 1; case UV_FS_READ: lua_pushlstring(L, (const char*)data->data, req->result); return 1; case UV_FS_SCANDIR: // Expose the userdata for the request. lua_rawgeti(L, LUA_REGISTRYINDEX, data->req_ref); return 1; #if LUV_UV_VERSION_GEQ(1, 28, 0) case UV_FS_OPENDIR: { int nentries; uv_dir_t* dir = (uv_dir_t*)req->ptr; lua_rawgeti(L, LUA_REGISTRYINDEX, data->data_ref); nentries = luaL_checkinteger(L, -1); lua_pop(L, 1); luaL_unref(L, LUA_REGISTRYINDEX, data->data_ref); data->data_ref = LUA_NOREF; (*(void**)lua_newuserdata(L, sizeof(void*))) = dir; lua_pushfstring(L, "uv_dir:%p", dir); dir->dirents = lua_newuserdata(L, sizeof(uv_dirent_t)*nentries); dir->nentries = nentries; lua_rawset(L, LUA_REGISTRYINDEX); luaL_getmetatable(L, "uv_dir"); lua_setmetatable(L, -2); return 1; } case UV_FS_READDIR: { if(req->result > 0) { size_t i; uv_dir_t *dir = (uv_dir_t*)req->ptr; lua_newtable(L); for(i=0; iresult; i++) { luv_push_dirent(L, dir->dirents+i, 1); lua_rawseti(L, -2, i+1); } } else lua_pushnil(L); return 1; } case UV_FS_CLOSEDIR: lua_pushboolean(L, 1); return 1; #endif default: lua_pushnil(L); lua_pushfstring(L, "UNKNOWN FS TYPE %d\n", req->fs_type); return 2; } } static void luv_fs_cb(uv_fs_t* req) { luv_req_t* data = (luv_req_t*)req->data; lua_State* L = data->ctx->L; int nargs = push_fs_result(L, req); if (nargs == 2 && lua_isnil(L, -nargs)) { // If it was an error, convert to (err, value) format. lua_remove(L, -nargs); nargs--; } else { // Otherwise insert a nil in front to convert to (err, value) format. lua_pushnil(L); lua_insert(L, -nargs - 1); nargs++; } if (req->fs_type == UV_FS_SCANDIR) { luv_fulfill_req(L, data, nargs); } else { // cleanup the uv_fs_t before the callback is called to avoid // a race condition when fs_close is called from within // a fs_readdir callback, see https://github.com/luvit/luv/issues/384 uv_fs_req_cleanup(req); req->data = NULL; luv_fulfill_req(L, data, nargs); luv_cleanup_req(L, data); } } // handle the FS call but don't return, instead set the local // variable 'nargs' to the number of return values #define FS_CALL_NORETURN(func, req, ...) { \ int ret, sync; \ luv_req_t* data = (luv_req_t*)req->data; \ sync = data->callback_ref == LUA_NOREF; \ ret = uv_fs_##func(data->ctx->loop, req, __VA_ARGS__, \ sync ? NULL : luv_fs_cb); \ if (req->fs_type != UV_FS_ACCESS && ret < 0) { \ lua_pushnil(L); \ if (req->path) { \ lua_pushfstring(L, "%s: %s: %s", \ uv_err_name(req->result), \ uv_strerror(req->result), req->path); \ } \ else { \ lua_pushfstring(L, "%s: %s", \ uv_err_name(req->result), \ uv_strerror(req->result)); \ } \ lua_pushstring(L, uv_err_name(req->result)); \ luv_cleanup_req(L, data); \ req->data = NULL; \ uv_fs_req_cleanup(req); \ nargs = 3; \ } \ else if (sync) { \ nargs = push_fs_result(L, req); \ if(req->fs_type != UV_FS_SCANDIR) { \ luv_cleanup_req(L, data); \ req->data = NULL; \ uv_fs_req_cleanup(req); \ } \ } \ else { \ lua_rawgeti(L, LUA_REGISTRYINDEX, data->req_ref); \ nargs = 1; \ } \ } #define FS_CALL(func, req, ...) { \ int nargs; \ FS_CALL_NORETURN(func, req, __VA_ARGS__) \ return nargs; \ } static int luv_fs_close(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(close, req, file); } static int luv_fs_open(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int flags = luv_check_flags(L, 2); int mode = luaL_checkinteger(L, 3); int ref = luv_check_continuation(L, 4); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(open, req, path, flags, mode); } static int luv_fs_read(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); int64_t len = luaL_checkinteger(L, 2); int64_t offset = luaL_checkinteger(L, 3); uv_buf_t buf; int ref; uv_fs_t* req; char* data = (char*)malloc(len); if (!data) return luaL_error(L, "Failure to allocate buffer"); buf = uv_buf_init(data, len); ref = luv_check_continuation(L, 4); req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); // TODO: find out why we can't just use req->ptr for the base ((luv_req_t*)req->data)->data = buf.base; FS_CALL(read, req, file, &buf, 1, offset); } static int luv_fs_unlink(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(unlink, req, path); } static int luv_fs_write(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); int64_t offset = luaL_checkinteger(L, 3); int ref = luv_check_continuation(L, 4); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); size_t count; uv_buf_t* bufs = luv_check_bufs(L, 2, &count, (luv_req_t*)req->data); int nargs; FS_CALL_NORETURN(write, req, file, bufs, count, offset); free(bufs); return nargs; } static int luv_fs_mkdir(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int mode = luaL_checkinteger(L, 2); int ref = luv_check_continuation(L, 3); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(mkdir, req, path, mode); } static int luv_fs_mkdtemp(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* tpl = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(mkdtemp, req, tpl); } #if LUV_UV_VERSION_GEQ(1, 34, 0) static int luv_fs_mkstemp(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* tpl = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(mkstemp, req, tpl); } #endif static int luv_fs_rmdir(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(rmdir, req, path); } static int luv_fs_scandir(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int flags = 0; // TODO: find out what these flags are. int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(scandir, req, path, flags); } static int luv_fs_scandir_next(lua_State* L) { uv_fs_t* req = luv_check_fs(L, 1); uv_dirent_t ent; int ret = uv_fs_scandir_next(req, &ent); if (ret == UV_EOF) { luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; uv_fs_req_cleanup(req); return 0; } if (ret < 0) return luv_error(L, ret); return luv_push_dirent(L, &ent, 0); } static int luv_fs_stat(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(stat, req, path); } static int luv_fs_fstat(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(fstat, req, file); } static int luv_fs_lstat(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(lstat, req, path); } static int luv_fs_rename(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); const char* new_path = luaL_checkstring(L, 2); int ref = luv_check_continuation(L, 3); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(rename, req, path, new_path); } static int luv_fs_fsync(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(fsync, req, file); } static int luv_fs_fdatasync(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(fdatasync, req, file); } static int luv_fs_ftruncate(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); int64_t offset = luaL_checkinteger(L, 2); int ref = luv_check_continuation(L, 3); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(ftruncate, req, file, offset); } static int luv_fs_sendfile(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file out_fd = luaL_checkinteger(L, 1); uv_file in_fd = luaL_checkinteger(L, 2); int64_t in_offset = luaL_checkinteger(L, 3); size_t length = luaL_checkinteger(L, 4); int ref = luv_check_continuation(L, 5); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(sendfile, req, out_fd, in_fd, in_offset, length); } static int luv_fs_access(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int amode = luv_check_amode(L, 2); int ref = luv_check_continuation(L, 3); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(access, req, path, amode); } static int luv_fs_chmod(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int mode = luaL_checkinteger(L, 2); int ref = luv_check_continuation(L, 3); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(chmod, req, path, mode); } static int luv_fs_fchmod(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); int mode = luaL_checkinteger(L, 2); int ref = luv_check_continuation(L, 3); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(fchmod, req, file, mode); } static int luv_fs_utime(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); double atime = luaL_checknumber(L, 2); double mtime = luaL_checknumber(L, 3); int ref = luv_check_continuation(L, 4); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(utime, req, path, atime, mtime); } static int luv_fs_futime(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); double atime = luaL_checknumber(L, 2); double mtime = luaL_checknumber(L, 3); int ref = luv_check_continuation(L, 4); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(futime, req, file, atime, mtime); } #if LUV_UV_VERSION_GEQ(1, 36, 0) static int luv_fs_lutime(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); double atime = luaL_checknumber(L, 2); double mtime = luaL_checknumber(L, 3); int ref = luv_check_continuation(L, 4); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(lutime, req, path, atime, mtime); } #endif static int luv_fs_link(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); const char* new_path = luaL_checkstring(L, 2); int ref = luv_check_continuation(L, 3); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(link, req, path, new_path); } static int luv_fs_symlink(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); const char* new_path = luaL_checkstring(L, 2); int flags = 0, ref; uv_fs_t* req; if (lua_type(L, 3) == LUA_TTABLE) { lua_getfield(L, 3, "dir"); if (lua_toboolean(L, -1)) flags |= UV_FS_SYMLINK_DIR; lua_pop(L, 1); lua_getfield(L, 3, "junction"); if (lua_toboolean(L, -1)) flags |= UV_FS_SYMLINK_JUNCTION; lua_pop(L, 1); } ref = luv_check_continuation(L, 4); req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(symlink, req, path, new_path, flags); } static int luv_fs_readlink(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(readlink, req, path); } #if LUV_UV_VERSION_GEQ(1, 8, 0) static int luv_fs_realpath(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(realpath, req, path); } #endif static int luv_fs_chown(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); uv_uid_t uid = luaL_checkinteger(L, 2); uv_uid_t gid = luaL_checkinteger(L, 3); int ref = luv_check_continuation(L, 4); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(chown, req, path, uid, gid); } static int luv_fs_fchown(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_file file = luaL_checkinteger(L, 1); uv_uid_t uid = luaL_checkinteger(L, 2); uv_uid_t gid = luaL_checkinteger(L, 3); int ref = luv_check_continuation(L, 4); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(fchown, req, file, uid, gid); } #if LUV_UV_VERSION_GEQ(1, 21, 0) static int luv_fs_lchown(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); uv_uid_t uid = luaL_checkinteger(L, 2); uv_uid_t gid = luaL_checkinteger(L, 3); int ref = luv_check_continuation(L, 4); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(lchown, req, path, uid, gid); } #endif #if LUV_UV_VERSION_GEQ(1, 14, 0) static int luv_fs_copyfile(lua_State*L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); const char* new_path = luaL_checkstring(L, 2); int flags = 0, ref; uv_fs_t* req; if (lua_type(L, 3) == LUA_TTABLE) { lua_getfield(L, 3, "excl"); if (lua_toboolean(L, -1)) flags |= UV_FS_COPYFILE_EXCL; lua_pop(L, 1); #if LUV_UV_VERSION_GEQ(1, 20, 0) lua_getfield(L, 3, "ficlone"); if (lua_toboolean(L, -1)) flags |= UV_FS_COPYFILE_FICLONE; lua_pop(L, 1); lua_getfield(L, 3, "ficlone_force"); if (lua_toboolean(L, -1)) flags |= UV_FS_COPYFILE_FICLONE_FORCE; lua_pop(L, 1); #endif } else if (lua_type(L, 3) == LUA_TNUMBER) { flags = lua_tointeger(L, 3); } ref = luv_check_continuation(L, 4); req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(copyfile, req, path, new_path, flags); } #endif #if LUV_UV_VERSION_GEQ(1, 28, 0) static uv_dir_t* luv_check_dir(lua_State* L, int idx) { uv_dir_t* dir = *(uv_dir_t**)luaL_checkudata(L, idx, "uv_dir"); return dir; } static int luv_fs_opendir(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); size_t nentries = luaL_optinteger(L, 3, 1); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); //make data_ref to nentries lua_pushinteger(L, nentries); ((luv_req_t*)req->data)->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); FS_CALL(opendir, req, path); } static int luv_fs_readdir(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_fs_t *req; uv_dir_t* dir = luv_check_dir(L, 1); int ref = luv_check_continuation(L, 2); req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(readdir, req, dir); } static int luv_fs_closedir(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_dir_t* dir = luv_check_dir(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t *req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); lua_pushfstring(L, "uv_dir:%p", dir); lua_pushnil(L); lua_rawset(L, LUA_REGISTRYINDEX); FS_CALL(closedir, req, dir); } static int luv_fs_dir_tostring(lua_State* L) { uv_dir_t* dir = luv_check_dir(L, 1); lua_pushfstring(L, "uv_dir_t: %p", dir); return 1; } static int luv_fs_dir_gc(lua_State* L) { uv_dir_t* dir = luv_check_dir(L, 1); lua_pushfstring(L, "uv_dir:%p", dir); lua_rawget(L, LUA_REGISTRYINDEX); if (!lua_isnil(L, -1)) { uv_fs_t req; luv_ctx_t* ctx = luv_context(L); uv_fs_closedir(ctx->loop, &req, dir, NULL); uv_fs_req_cleanup(&req); lua_pushfstring(L, "uv_dir:%p", dir); lua_pushnil(L); lua_rawset(L, LUA_REGISTRYINDEX); } lua_pop(L, 1); return 0; } #endif #if LUV_UV_VERSION_GEQ(1, 31, 0) static int luv_fs_statfs(lua_State* L) { luv_ctx_t* ctx = luv_context(L); const char* path = luaL_checkstring(L, 1); int ref = luv_check_continuation(L, 2); uv_fs_t* req = (uv_fs_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); FS_CALL(statfs, req, path); } #endif luv-1.36.0-0/src/fs_event.c000066400000000000000000000056401364617304100153220ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_fs_event_t* luv_check_fs_event(lua_State* L, int index) { uv_fs_event_t* handle = (uv_fs_event_t*)luv_checkudata(L, index, "uv_fs_event"); luaL_argcheck(L, handle->type == UV_FS_EVENT && handle->data, index, "Expected uv_fs_event_t"); return handle; } static int luv_new_fs_event(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_fs_event_t* handle = (uv_fs_event_t*)luv_newuserdata(L, sizeof(*handle)); int ret = uv_fs_event_init(ctx->loop, handle); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static void luv_fs_event_cb(uv_fs_event_t* handle, const char* filename, int events, int status) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; // err luv_status(L, status); // filename lua_pushstring(L, filename); // events lua_newtable(L); if (events & UV_RENAME) { lua_pushboolean(L, 1); lua_setfield(L, -2, "rename"); } if (events & UV_CHANGE) { lua_pushboolean(L, 1); lua_setfield(L, -2, "change"); } luv_call_callback(L, (luv_handle_t*)handle->data, LUV_FS_EVENT, 3); } static int luv_fs_event_start(lua_State* L) { uv_fs_event_t* handle = luv_check_fs_event(L, 1); const char* path = luaL_checkstring(L, 2); int flags = 0, ret; luaL_checktype(L, 3, LUA_TTABLE); lua_getfield(L, 3, "watch_entry"); if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_WATCH_ENTRY; lua_pop(L, 1); lua_getfield(L, 3, "stat"); if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_STAT; lua_pop(L, 1); lua_getfield(L, 3, "recursive"); if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_RECURSIVE; lua_pop(L, 1); luv_check_callback(L, (luv_handle_t*)handle->data, LUV_FS_EVENT, 4); ret = uv_fs_event_start(handle, luv_fs_event_cb, path, flags); return luv_result(L, ret); } static int luv_fs_event_stop(lua_State* L) { uv_fs_event_t* handle = luv_check_fs_event(L, 1); int ret = uv_fs_event_stop(handle); return luv_result(L, ret); } static int luv_fs_event_getpath(lua_State* L) { uv_fs_event_t* handle = luv_check_fs_event(L, 1); size_t len = 2*PATH_MAX; char buf[2*PATH_MAX]; int ret = uv_fs_event_getpath(handle, buf, &len); if (ret < 0) return luv_error(L, ret); lua_pushlstring(L, buf, len); return 1; } luv-1.36.0-0/src/fs_poll.c000066400000000000000000000050011364617304100151360ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "luv.h" static uv_fs_poll_t* luv_check_fs_poll(lua_State* L, int index) { uv_fs_poll_t* handle = (uv_fs_poll_t*)luv_checkudata(L, index, "uv_fs_poll"); luaL_argcheck(L, handle->type == UV_FS_POLL && handle->data, index, "Expected uv_fs_poll_t"); return handle; } static int luv_new_fs_poll(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_fs_poll_t* handle = (uv_fs_poll_t*)luv_newuserdata(L, sizeof(*handle)); int ret = uv_fs_poll_init(ctx->loop, handle); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static void luv_fs_poll_cb(uv_fs_poll_t* handle, int status, const uv_stat_t* prev, const uv_stat_t* curr) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; // err luv_status(L, status); // prev if (prev) { luv_push_stats_table(L, prev); } else { lua_pushnil(L); } // curr if (curr) { luv_push_stats_table(L, curr); } else { lua_pushnil(L); } luv_call_callback(L, (luv_handle_t*)handle->data, LUV_FS_POLL, 3); } static int luv_fs_poll_start(lua_State* L) { uv_fs_poll_t* handle = luv_check_fs_poll(L, 1); const char* path = luaL_checkstring(L, 2); unsigned int interval = luaL_checkinteger(L, 3); int ret; luv_check_callback(L, (luv_handle_t*)handle->data, LUV_FS_POLL, 4); ret = uv_fs_poll_start(handle, luv_fs_poll_cb, path, interval); return luv_result(L, ret); } static int luv_fs_poll_stop(lua_State* L) { uv_fs_poll_t* handle = luv_check_fs_poll(L, 1); int ret = uv_fs_poll_stop(handle); return luv_result(L, ret); } static int luv_fs_poll_getpath(lua_State* L) { uv_fs_poll_t* handle = luv_check_fs_poll(L, 1); size_t len = 2*PATH_MAX; char buf[2*PATH_MAX]; int ret = uv_fs_poll_getpath(handle, buf, &len); if (ret < 0) return luv_error(L, ret); lua_pushlstring(L, buf, len); return 1; } luv-1.36.0-0/src/handle.c000066400000000000000000000122271364617304100147430ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static void* luv_newuserdata(lua_State* L, size_t sz) { void* handle = malloc(sz); if (handle) { *(void**)lua_newuserdata(L, sizeof(void*)) = handle; } return handle; } static void* luv_checkudata(lua_State* L, int ud, const char* tname) { return *(void**) luaL_checkudata(L, ud, tname); } static uv_handle_t* luv_check_handle(lua_State* L, int index) { int isHandle; uv_handle_t* handle; void *udata; if (!(udata = lua_touserdata(L, index))) { goto fail; } if (!(handle = *(uv_handle_t**) udata)) { goto fail; } if (!handle->data) { goto fail; } lua_getfield(L, LUA_REGISTRYINDEX, "uv_handle"); lua_getmetatable(L, index < 0 ? index - 1 : index); lua_rawget(L, -2); isHandle = lua_toboolean(L, -1); lua_pop(L, 2); if (isHandle) { return handle; } fail: luaL_argerror(L, index, "Expected uv_handle userdata"); return NULL; } // Show the libuv type instead of generic "userdata" static int luv_handle_tostring(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); switch (handle->type) { #define XX(uc, lc) case UV_##uc: lua_pushfstring(L, "uv_"#lc"_t: %p", handle); break; UV_HANDLE_TYPE_MAP(XX) #undef XX default: lua_pushfstring(L, "uv_handle_t: %p", handle); break; } return 1; } static int luv_is_active(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); int ret = uv_is_active(handle); if (ret < 0) return luv_error(L, ret); lua_pushboolean(L, ret); return 1; } static int luv_is_closing(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); int ret = uv_is_closing(handle); if (ret < 0) return luv_error(L, ret); lua_pushboolean(L, ret); return 1; } static void luv_close_cb(uv_handle_t* handle) { lua_State* L; luv_handle_t* data = (luv_handle_t*)handle->data; if (!data) return; L = data->ctx->L; luv_call_callback(L, data, LUV_CLOSED, 0); luv_unref_handle(L, data); } static int luv_close(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); if (uv_is_closing(handle)) { luaL_error(L, "handle %p is already closing", handle); } if (!lua_isnoneornil(L, 2)) { luv_check_callback(L, (luv_handle_t*)handle->data, LUV_CLOSED, 2); } uv_close(handle, luv_close_cb); return 0; } static void luv_handle_free(uv_handle_t* handle) { luv_handle_t* data = (luv_handle_t*)handle->data; if (data) { if (data->extra_gc) data->extra_gc(data->extra); free(data); } free(handle); } static void luv_gc_cb(uv_handle_t* handle) { luv_close_cb(handle); luv_handle_free(handle); } static int luv_handle_gc(lua_State* L) { uv_handle_t** udata = (uv_handle_t**)lua_touserdata(L, 1); uv_handle_t* handle = *udata; // Only cleanup if the handle hasn't been cleaned up yet. if (handle) { if (!uv_is_closing(handle)) { // If the handle is not closed yet, close it first before freeing memory. uv_close(handle, luv_gc_cb); } else { // Otherwise, free the memory right away. luv_handle_free(handle); } // Mark as cleaned up by wiping the dangling pointer. *udata = NULL; } return 0; } static int luv_ref(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); uv_ref(handle); return 0; } static int luv_unref(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); uv_unref(handle); return 0; } static int luv_has_ref(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); int ret = uv_has_ref(handle); if (ret < 0) return luv_error(L, ret); lua_pushboolean(L, ret); return 1; } static int luv_send_buffer_size(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); int value = luaL_optinteger(L, 2, 0); int ret; if (value == 0) { // get ret = uv_send_buffer_size(handle, &value); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, value); return 1; } else { // set ret = uv_send_buffer_size(handle, &value); return luv_result(L, ret); } } static int luv_recv_buffer_size(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); int value = luaL_optinteger(L, 2, 0); int ret; if (value == 0) { // get ret = uv_recv_buffer_size(handle, &value); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, value); return 1; } else { // set ret = uv_recv_buffer_size(handle, &value); return luv_result(L, ret); } } static int luv_fileno(lua_State* L) { uv_handle_t* handle = luv_check_handle(L, 1); uv_os_fd_t fd; int ret = uv_fileno(handle, &fd); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, (LUA_INTEGER)(ptrdiff_t)fd); return 1; } luv-1.36.0-0/src/idle.c000066400000000000000000000033701364617304100144240ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_idle_t* luv_check_idle(lua_State* L, int index) { uv_idle_t* handle = (uv_idle_t*)luv_checkudata(L, index, "uv_idle"); luaL_argcheck(L, handle->type == UV_IDLE && handle->data, index, "Expected uv_idle_t"); return handle; } static int luv_new_idle(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_idle_t* handle = (uv_idle_t*)luv_newuserdata(L, sizeof(*handle)); int ret = uv_idle_init(ctx->loop, handle); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static void luv_idle_cb(uv_idle_t* handle) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; luv_call_callback(L, data, LUV_IDLE, 0); } static int luv_idle_start(lua_State* L) { uv_idle_t* handle = luv_check_idle(L, 1); int ret; luv_check_callback(L, (luv_handle_t *)handle->data, LUV_IDLE, 2); ret = uv_idle_start(handle, luv_idle_cb); return luv_result(L, ret); } static int luv_idle_stop(lua_State* L) { uv_idle_t* handle = luv_check_idle(L, 1); int ret = uv_idle_stop(handle); return luv_result(L, ret); } luv-1.36.0-0/src/lhandle.c000066400000000000000000000061501364617304100151150ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "lhandle.h" static luv_handle_t* luv_setup_handle(lua_State* L, luv_ctx_t* ctx) { luv_handle_t* data; const uv_handle_t* handle; void *udata; if (!(udata = lua_touserdata(L, -1))) { luaL_error(L, "NULL userdata"); return NULL; } handle = *(uv_handle_t**)udata; luaL_checktype(L, -1, LUA_TUSERDATA); data = (luv_handle_t*)malloc(sizeof(*data)); if (!data) luaL_error(L, "Can't allocate luv handle"); #define XX(uc, lc) case UV_##uc: \ luaL_getmetatable(L, "uv_"#lc); \ break; switch (handle->type) { UV_HANDLE_TYPE_MAP(XX) default: luaL_error(L, "Unknown handle type"); return NULL; } #undef XX lua_setmetatable(L, -2); lua_pushvalue(L, -1); data->ref = luaL_ref(L, LUA_REGISTRYINDEX); data->callbacks[0] = LUA_NOREF; data->callbacks[1] = LUA_NOREF; data->ctx = ctx; data->extra = NULL; data->extra_gc = NULL; return data; } static void luv_check_callback(lua_State* L, luv_handle_t* data, luv_callback_id id, int index) { luv_check_callable(L, index); luaL_unref(L, LUA_REGISTRYINDEX, data->callbacks[id]); lua_pushvalue(L, index); data->callbacks[id] = luaL_ref(L, LUA_REGISTRYINDEX); } static int luv_traceback (lua_State *L) { if (!lua_isstring(L, 1)) /* 'message' not a string? */ return 1; /* keep it intact */ lua_pushglobaltable(L); lua_getfield(L, -1, "debug"); lua_remove(L, -2); if (!lua_istable(L, -1)) { lua_pop(L, 1); return 1; } lua_getfield(L, -1, "traceback"); if (!lua_isfunction(L, -1)) { lua_pop(L, 2); return 1; } lua_pushvalue(L, 1); /* pass error message */ lua_pushinteger(L, 2); /* skip this function and traceback */ lua_call(L, 2, 1); /* call debug.traceback */ return 1; } static void luv_call_callback(lua_State* L, luv_handle_t* data, luv_callback_id id, int nargs) { luv_ctx_t* ctx = data->ctx; int ref = data->callbacks[id]; if (ref == LUA_NOREF) { lua_pop(L, nargs); } else { // Get the callback lua_rawgeti(L, LUA_REGISTRYINDEX, ref); // And insert it before the args if there are any. if (nargs) { lua_insert(L, -1 - nargs); } ctx->pcall(L, nargs, 0, 0); } } static void luv_unref_handle(lua_State* L, luv_handle_t* data) { luaL_unref(L, LUA_REGISTRYINDEX, data->ref); luaL_unref(L, LUA_REGISTRYINDEX, data->callbacks[0]); luaL_unref(L, LUA_REGISTRYINDEX, data->callbacks[1]); } static void luv_find_handle(lua_State* L, luv_handle_t* data) { lua_rawgeti(L, LUA_REGISTRYINDEX, data->ref); } luv-1.36.0-0/src/lhandle.h000066400000000000000000000026171364617304100151260ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LUV_LHANDLE_H #define LUV_LHANDLE_H #include "luv.h" /* There are two slots for holding callbacks. One is for the CLOSED event. The other slot is for all others since they never conflict in practice. */ #define luv_callback_id int #define LUV_CLOSED 0 #define LUV_TIMEOUT 1 #define LUV_PREPARE 1 #define LUV_IDLE 1 #define LUV_CHECK 1 #define LUV_ASYNC 1 #define LUV_POLL 1 #define LUV_SIGNAL 1 #define LUV_EXIT 1 #define LUV_CONNECTION 1 #define LUV_READ 1 #define LUV_RECV 1 #define LUV_FS_EVENT 1 #define LUV_FS_POLL 1 #define LUV_RESET 1 typedef void (*luv_handle_extra_gc) (void* ptr); /* Ref for userdata and event callbacks */ typedef struct { int ref; int callbacks[2]; luv_ctx_t* ctx; void* extra; luv_handle_extra_gc extra_gc; } luv_handle_t; #endif luv-1.36.0-0/src/loop.c000066400000000000000000000050751364617304100144640ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static int luv_loop_close(lua_State* L) { int ret = uv_loop_close(luv_loop(L)); if (ret < 0) return luv_error(L, ret); luv_set_loop(L, NULL); lua_pushinteger(L, ret); return 1; } // These are the same order as uv_run_mode which also starts at 0 static const char *const luv_runmodes[] = { "default", "once", "nowait", NULL }; static int luv_run(lua_State* L) { int mode = luaL_checkoption(L, 1, "default", luv_runmodes); int ret = uv_run(luv_loop(L), (uv_run_mode)mode); if (ret < 0) return luv_error(L, ret); lua_pushboolean(L, ret); return 1; } static int luv_loop_alive(lua_State* L) { int ret = uv_loop_alive(luv_loop(L)); if (ret < 0) return luv_error(L, ret); lua_pushboolean(L, ret); return 1; } static int luv_stop(lua_State* L) { uv_stop(luv_loop(L)); return 0; } static int luv_backend_fd(lua_State* L) { int ret = uv_backend_fd(luv_loop(L)); // -1 is returned when there is no backend fd (like on Windows) if (ret == -1) lua_pushnil(L); else lua_pushinteger(L, ret); return 1; } static int luv_backend_timeout(lua_State* L) { int ret = uv_backend_timeout(luv_loop(L)); lua_pushinteger(L, ret); return 1; } static int luv_now(lua_State* L) { uint64_t now = uv_now(luv_loop(L)); lua_pushinteger(L, now); return 1; } static int luv_update_time(lua_State* L) { uv_update_time(luv_loop(L)); return 0; } static void luv_walk_cb(uv_handle_t* handle, void* arg) { lua_State* L = (lua_State*)arg; luv_handle_t* data = (luv_handle_t*)handle->data; // Sanity check // Most invalid values are large and refs are small, 0x1000000 is arbitrary. assert(data && data->ref < 0x1000000); lua_pushvalue(L, 1); // Copy the function luv_find_handle(L, data); // Get the userdata data->ctx->pcall(L, 1, 0, 0); // Call the function } static int luv_walk(lua_State* L) { luaL_checktype(L, 1, LUA_TFUNCTION); uv_walk(luv_loop(L), luv_walk_cb, L); return 0; } luv-1.36.0-0/src/lreq.c000066400000000000000000000044351364617304100144550ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static int luv_check_continuation(lua_State* L, int index) { if (lua_isnoneornil(L, index)) return LUA_NOREF; luv_check_callable(L, index); lua_pushvalue(L, index); return luaL_ref(L, LUA_REGISTRYINDEX); } // Store a lua callback in a luv_req for the continuation. // The uv_req_t is assumed to be at the top of the stack static luv_req_t* luv_setup_req(lua_State* L, luv_ctx_t* ctx, int cb_ref) { luv_req_t* data; luaL_checktype(L, -1, LUA_TUSERDATA); data = (luv_req_t*)malloc(sizeof(*data)); if (!data) luaL_error(L, "Problem allocating luv request"); luaL_getmetatable(L, "uv_req"); lua_setmetatable(L, -2); lua_pushvalue(L, -1); data->req_ref = luaL_ref(L, LUA_REGISTRYINDEX); data->callback_ref = cb_ref; data->data_ref = LUA_NOREF; data->ctx = ctx; data->data = NULL; return data; } static void luv_fulfill_req(lua_State* L, luv_req_t* data, int nargs) { if (data->callback_ref == LUA_NOREF) { lua_pop(L, nargs); } else { // Get the callback lua_rawgeti(L, LUA_REGISTRYINDEX, data->callback_ref); // And insert it before the args if there are any. if (nargs) { lua_insert(L, -1 - nargs); } data->ctx->pcall(L, nargs, 0, 0); } } static void luv_cleanup_req(lua_State* L, luv_req_t* data) { int i; luaL_unref(L, LUA_REGISTRYINDEX, data->req_ref); luaL_unref(L, LUA_REGISTRYINDEX, data->callback_ref); if (data->data_ref == LUV_REQ_MULTIREF) { for (i = 0; ((int*)(data->data))[i] != LUA_NOREF; i++) { luaL_unref(L, LUA_REGISTRYINDEX, ((int*)(data->data))[i]); } } else luaL_unref(L, LUA_REGISTRYINDEX, data->data_ref); free(data->data); free(data); } luv-1.36.0-0/src/lreq.h000066400000000000000000000020441364617304100144540ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LUV_LREQ_H #define LUV_LREQ_H #include "luv.h" typedef struct { int req_ref; /* ref for uv_req_t's userdata */ int callback_ref; /* ref for callback */ int data_ref; /* ref for write data */ luv_ctx_t* ctx; /* context for callback */ void* data; /* extra data */ } luv_req_t; // This is an arbitrary value that we can assume will never be returned by luaL_ref #define LUV_REQ_MULTIREF (-0x1234) #endif luv-1.36.0-0/src/lthreadpool.h000066400000000000000000000031531364617304100160300ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LUV_LTHREADPOOL_H #define LUV_LTHREADPOOL_H #include "luv.h" #define LUV_THREAD_MAXNUM_ARG 9 typedef struct { // support basic lua type LUA_TNIL, LUA_TBOOLEAN, LUA_TNUMBER, LUA_TSTRING // and support uv_handle_t userdata int type; union { lua_Number num; int boolean; struct { const char* base; size_t len; } str; struct { const void* data; size_t size; const char* metaname; } udata; } val; int ref[2]; // ref of string or userdata } luv_val_t; typedef struct { int argc; int flags; // control gc lua_State *L; luv_val_t argv[LUV_THREAD_MAXNUM_ARG]; } luv_thread_arg_t; //luajit miss LUA_OK #ifndef LUA_OK #define LUA_OK 0 #endif //LUV flags for thread or threadpool args #define LUVF_THREAD_SIDE_MAIN 0x00 #define LUVF_THREAD_SIDE_CHILD 0x01 #define LUVF_THREAD_MODE_ASYNC 0x02 #define LUVF_THREAD_SIDE(i) ((i)&0x01) #define LUVF_THREAD_ASYNC(i) ((i)&0x02) #endif //LUV_LTHREADPOOL_H luv-1.36.0-0/src/luv.c000066400000000000000000000475501364617304100143250ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #if (LUA_VERSION_NUM != 503) #include "compat-5.3.h" #endif #include "luv.h" #include "util.c" #include "lhandle.c" #include "lreq.c" #include "loop.c" #include "req.c" #include "handle.c" #include "timer.c" #include "prepare.c" #include "check.c" #include "idle.c" #include "async.c" #include "poll.c" #include "signal.c" #include "process.c" #include "stream.c" #include "tcp.c" #include "pipe.c" #include "tty.c" #include "udp.c" #include "fs_event.c" #include "fs_poll.c" #include "fs.c" #include "dns.c" #include "thread.c" #include "work.c" #include "misc.c" #include "constants.c" static const luaL_Reg luv_functions[] = { // loop.c {"loop_close", luv_loop_close}, {"run", luv_run}, {"loop_alive", luv_loop_alive}, {"stop", luv_stop}, {"backend_fd", luv_backend_fd}, {"backend_timeout", luv_backend_timeout}, {"now", luv_now}, {"update_time", luv_update_time}, {"walk", luv_walk}, // req.c {"cancel", luv_cancel}, // handle.c {"is_active", luv_is_active}, {"is_closing", luv_is_closing}, {"close", luv_close}, {"ref", luv_ref}, {"unref", luv_unref}, {"has_ref", luv_has_ref}, {"send_buffer_size", luv_send_buffer_size}, {"recv_buffer_size", luv_recv_buffer_size}, {"fileno", luv_fileno}, // timer.c {"new_timer", luv_new_timer}, {"timer_start", luv_timer_start}, {"timer_stop", luv_timer_stop}, {"timer_again", luv_timer_again}, {"timer_set_repeat", luv_timer_set_repeat}, {"timer_get_repeat", luv_timer_get_repeat}, // prepare.c {"new_prepare", luv_new_prepare}, {"prepare_start", luv_prepare_start}, {"prepare_stop", luv_prepare_stop}, // check.c {"new_check", luv_new_check}, {"check_start", luv_check_start}, {"check_stop", luv_check_stop}, // idle.c {"new_idle", luv_new_idle}, {"idle_start", luv_idle_start}, {"idle_stop", luv_idle_stop}, // async.c {"new_async", luv_new_async}, {"async_send", luv_async_send}, // poll.c {"new_poll", luv_new_poll}, {"new_socket_poll", luv_new_socket_poll}, {"poll_start", luv_poll_start}, {"poll_stop", luv_poll_stop}, // signal.c {"new_signal", luv_new_signal}, {"signal_start", luv_signal_start}, #if LUV_UV_VERSION_GEQ(1, 12, 0) {"signal_start_oneshot", luv_signal_start_oneshot}, #endif {"signal_stop", luv_signal_stop}, // process.c {"disable_stdio_inheritance", luv_disable_stdio_inheritance}, {"spawn", luv_spawn}, {"process_kill", luv_process_kill}, {"kill", luv_kill}, // stream.c {"shutdown", luv_shutdown}, {"listen", luv_listen}, {"accept", luv_accept}, {"read_start", luv_read_start}, {"read_stop", luv_read_stop}, {"write", luv_write}, {"write2", luv_write2}, {"try_write", luv_try_write}, {"is_readable", luv_is_readable}, {"is_writable", luv_is_writable}, {"stream_set_blocking", luv_stream_set_blocking}, #if LUV_UV_VERSION_GEQ(1, 19, 0) {"stream_get_write_queue_size", luv_stream_get_write_queue_size}, #endif // tcp.c {"new_tcp", luv_new_tcp}, {"tcp_open", luv_tcp_open}, {"tcp_nodelay", luv_tcp_nodelay}, {"tcp_keepalive", luv_tcp_keepalive}, {"tcp_simultaneous_accepts", luv_tcp_simultaneous_accepts}, {"tcp_bind", luv_tcp_bind}, {"tcp_getpeername", luv_tcp_getpeername}, {"tcp_getsockname", luv_tcp_getsockname}, {"tcp_connect", luv_tcp_connect}, {"tcp_write_queue_size", luv_write_queue_size}, #if LUV_UV_VERSION_GEQ(1, 32, 0) {"tcp_close_reset", luv_tcp_close_reset}, #endif // pipe.c {"new_pipe", luv_new_pipe}, {"pipe_open", luv_pipe_open}, {"pipe_bind", luv_pipe_bind}, {"pipe_connect", luv_pipe_connect}, {"pipe_getsockname", luv_pipe_getsockname}, #if LUV_UV_VERSION_GEQ(1, 3, 0) {"pipe_getpeername", luv_pipe_getpeername}, #endif {"pipe_pending_instances", luv_pipe_pending_instances}, {"pipe_pending_count", luv_pipe_pending_count}, {"pipe_pending_type", luv_pipe_pending_type}, // tty.c {"new_tty", luv_new_tty}, {"tty_set_mode", luv_tty_set_mode}, {"tty_reset_mode", luv_tty_reset_mode}, {"tty_get_winsize", luv_tty_get_winsize}, #if LUV_UV_VERSION_GEQ(1, 33, 0) {"tty_set_vterm_state", luv_tty_set_vterm_state}, {"tty_get_vterm_state", luv_tty_get_vterm_state}, #endif // udp.c {"new_udp", luv_new_udp}, {"udp_get_send_queue_size", luv_udp_get_send_queue_size}, {"udp_get_send_queue_count", luv_udp_get_send_queue_count}, {"udp_open", luv_udp_open}, {"udp_bind", luv_udp_bind}, {"udp_getsockname", luv_udp_getsockname}, {"udp_set_membership", luv_udp_set_membership}, {"udp_set_multicast_loop", luv_udp_set_multicast_loop}, {"udp_set_multicast_ttl", luv_udp_set_multicast_ttl}, {"udp_set_multicast_interface", luv_udp_set_multicast_interface}, {"udp_set_broadcast", luv_udp_set_broadcast}, {"udp_set_ttl", luv_udp_set_ttl}, {"udp_send", luv_udp_send}, {"udp_try_send", luv_udp_try_send}, {"udp_recv_start", luv_udp_recv_start}, {"udp_recv_stop", luv_udp_recv_stop}, #if LUV_UV_VERSION_GEQ(1, 27, 0) {"udp_connect", luv_udp_connect}, {"udp_getpeername", luv_udp_getpeername}, #endif // fs_event.c {"new_fs_event", luv_new_fs_event}, {"fs_event_start", luv_fs_event_start}, {"fs_event_stop", luv_fs_event_stop}, {"fs_event_getpath", luv_fs_event_getpath}, // fs_poll.c {"new_fs_poll", luv_new_fs_poll}, {"fs_poll_start", luv_fs_poll_start}, {"fs_poll_stop", luv_fs_poll_stop}, {"fs_poll_getpath", luv_fs_poll_getpath}, // fs.c {"fs_close", luv_fs_close}, {"fs_open", luv_fs_open}, {"fs_read", luv_fs_read}, {"fs_unlink", luv_fs_unlink}, {"fs_write", luv_fs_write}, {"fs_mkdir", luv_fs_mkdir}, {"fs_mkdtemp", luv_fs_mkdtemp}, #if LUV_UV_VERSION_GEQ(1, 34, 0) {"fs_mkstemp", luv_fs_mkstemp}, #endif {"fs_rmdir", luv_fs_rmdir}, {"fs_scandir", luv_fs_scandir}, {"fs_scandir_next", luv_fs_scandir_next}, {"fs_stat", luv_fs_stat}, {"fs_fstat", luv_fs_fstat}, {"fs_lstat", luv_fs_lstat}, {"fs_rename", luv_fs_rename}, {"fs_fsync", luv_fs_fsync}, {"fs_fdatasync", luv_fs_fdatasync}, {"fs_ftruncate", luv_fs_ftruncate}, {"fs_sendfile", luv_fs_sendfile}, {"fs_access", luv_fs_access}, {"fs_chmod", luv_fs_chmod}, {"fs_fchmod", luv_fs_fchmod}, {"fs_utime", luv_fs_utime}, {"fs_futime", luv_fs_futime}, #if LUV_UV_VERSION_GEQ(1, 36, 0) {"fs_lutime", luv_fs_lutime}, #endif {"fs_link", luv_fs_link}, {"fs_symlink", luv_fs_symlink}, {"fs_readlink", luv_fs_readlink}, #if LUV_UV_VERSION_GEQ(1, 8, 0) {"fs_realpath", luv_fs_realpath}, #endif {"fs_chown", luv_fs_chown}, {"fs_fchown", luv_fs_fchown}, #if LUV_UV_VERSION_GEQ(1, 21, 0) {"fs_lchown", luv_fs_lchown}, #endif #if LUV_UV_VERSION_GEQ(1, 14, 0) {"fs_copyfile", luv_fs_copyfile }, #endif #if LUV_UV_VERSION_GEQ(1, 28, 0) {"fs_opendir", luv_fs_opendir}, {"fs_readdir", luv_fs_readdir}, {"fs_closedir", luv_fs_closedir}, #endif #if LUV_UV_VERSION_GEQ(1, 31, 0) {"fs_statfs", luv_fs_statfs}, #endif // dns.c {"getaddrinfo", luv_getaddrinfo}, {"getnameinfo", luv_getnameinfo}, // misc.c {"chdir", luv_chdir}, #if LUV_UV_VERSION_GEQ(1, 9, 0) {"os_homedir", luv_os_homedir}, {"os_tmpdir", luv_os_tmpdir}, {"os_get_passwd", luv_os_get_passwd}, #endif {"cpu_info", luv_cpu_info}, {"cwd", luv_cwd}, {"exepath", luv_exepath}, {"get_process_title", luv_get_process_title}, #if LUV_UV_VERSION_GEQ(1, 29, 0) {"get_constrained_memory", luv_get_constrained_memory}, #endif {"get_total_memory", luv_get_total_memory}, {"get_free_memory", luv_get_free_memory}, {"getpid", luv_getpid}, #ifndef _WIN32 {"getuid", luv_getuid}, {"setuid", luv_setuid}, {"getgid", luv_getgid}, {"setgid", luv_setgid}, #endif {"getrusage", luv_getrusage}, {"guess_handle", luv_guess_handle}, {"hrtime", luv_hrtime}, {"interface_addresses", luv_interface_addresses}, {"loadavg", luv_loadavg}, {"resident_set_memory", luv_resident_set_memory}, {"set_process_title", luv_set_process_title}, {"uptime", luv_uptime}, {"version", luv_version}, {"version_string", luv_version_string}, #ifndef _WIN32 #if LUV_UV_VERSION_GEQ(1, 8, 0) {"print_all_handles", luv_print_all_handles}, {"print_active_handles", luv_print_active_handles}, #endif #endif #if LUV_UV_VERSION_GEQ(1, 12, 0) {"os_getenv", luv_os_getenv}, {"os_setenv", luv_os_setenv}, {"os_unsetenv", luv_os_unsetenv}, {"os_gethostname", luv_os_gethostname}, #endif #if LUV_UV_VERSION_GEQ(1, 16, 0) {"if_indextoname", luv_if_indextoname}, {"if_indextoiid", luv_if_indextoiid}, {"os_getppid", luv_os_getppid }, #endif #if LUV_UV_VERSION_GEQ(1, 18, 0) {"os_getpid", luv_os_getpid}, #endif #if LUV_UV_VERSION_GEQ(1, 23, 0) {"os_getpriority", luv_os_getpriority}, {"os_setpriority", luv_os_setpriority}, #endif #if LUV_UV_VERSION_GEQ(1, 25, 0) {"os_uname", luv_os_uname}, #endif #if LUV_UV_VERSION_GEQ(1, 28, 0) {"gettimeofday", luv_gettimeofday}, #endif #if LUV_UV_VERSION_GEQ(1, 31, 0) {"os_environ", luv_os_environ}, #endif #if LUV_UV_VERSION_GEQ(1, 33, 0) {"random", luv_random}, #endif {"sleep", luv_sleep}, // thread.c {"new_thread", luv_new_thread}, {"thread_equal", luv_thread_equal}, {"thread_self", luv_thread_self}, {"thread_join", luv_thread_join}, // work.c {"new_work", luv_new_work}, {"queue_work", luv_queue_work}, // util.c #if LUV_UV_VERSION_GEQ(1, 10, 0) {"translate_sys_error", luv_translate_sys_error}, #endif {NULL, NULL} }; static const luaL_Reg luv_handle_methods[] = { // handle.c {"is_active", luv_is_active}, {"is_closing", luv_is_closing}, {"close", luv_close}, {"ref", luv_ref}, {"unref", luv_unref}, {"has_ref", luv_has_ref}, {"send_buffer_size", luv_send_buffer_size}, {"recv_buffer_size", luv_recv_buffer_size}, {"fileno", luv_fileno}, {NULL, NULL} }; static const luaL_Reg luv_async_methods[] = { {"send", luv_async_send}, {NULL, NULL} }; static const luaL_Reg luv_check_methods[] = { {"start", luv_check_start}, {"stop", luv_check_stop}, {NULL, NULL} }; static const luaL_Reg luv_fs_event_methods[] = { {"start", luv_fs_event_start}, {"stop", luv_fs_event_stop}, {"getpath", luv_fs_event_getpath}, {NULL, NULL} }; static const luaL_Reg luv_fs_poll_methods[] = { {"start", luv_fs_poll_start}, {"stop", luv_fs_poll_stop}, {"getpath", luv_fs_poll_getpath}, {NULL, NULL} }; static const luaL_Reg luv_idle_methods[] = { {"start", luv_idle_start}, {"stop", luv_idle_stop}, {NULL, NULL} }; static const luaL_Reg luv_stream_methods[] = { {"shutdown", luv_shutdown}, {"listen", luv_listen}, {"accept", luv_accept}, {"read_start", luv_read_start}, {"read_stop", luv_read_stop}, {"write", luv_write}, {"write2", luv_write2}, {"try_write", luv_try_write}, {"is_readable", luv_is_readable}, {"is_writable", luv_is_writable}, {"set_blocking", luv_stream_set_blocking}, #if LUV_UV_VERSION_GEQ(1, 19, 0) {"get_write_queue_size", luv_stream_get_write_queue_size}, #endif {NULL, NULL} }; static const luaL_Reg luv_pipe_methods[] = { {"open", luv_pipe_open}, {"bind", luv_pipe_bind}, {"connect", luv_pipe_connect}, {"getsockname", luv_pipe_getsockname}, #if LUV_UV_VERSION_GEQ(1, 3, 0) {"getpeername", luv_pipe_getpeername}, #endif {"pending_instances", luv_pipe_pending_instances}, {"pending_count", luv_pipe_pending_count}, {"pending_type", luv_pipe_pending_type}, {NULL, NULL} }; static const luaL_Reg luv_poll_methods[] = { {"start", luv_poll_start}, {"stop", luv_poll_stop}, {NULL, NULL} }; static const luaL_Reg luv_prepare_methods[] = { {"start", luv_prepare_start}, {"stop", luv_prepare_stop}, {NULL, NULL} }; static const luaL_Reg luv_process_methods[] = { {"kill", luv_process_kill}, {NULL, NULL} }; static const luaL_Reg luv_tcp_methods[] = { {"open", luv_tcp_open}, {"nodelay", luv_tcp_nodelay}, {"keepalive", luv_tcp_keepalive}, {"simultaneous_accepts", luv_tcp_simultaneous_accepts}, {"bind", luv_tcp_bind}, {"getpeername", luv_tcp_getpeername}, {"getsockname", luv_tcp_getsockname}, {"connect", luv_tcp_connect}, {"write_queue_size", luv_write_queue_size}, #if LUV_UV_VERSION_GEQ(1, 32, 0) {"close_reset", luv_tcp_close_reset}, #endif {NULL, NULL} }; static const luaL_Reg luv_timer_methods[] = { {"start", luv_timer_start}, {"stop", luv_timer_stop}, {"again", luv_timer_again}, {"set_repeat", luv_timer_set_repeat}, {"get_repeat", luv_timer_get_repeat}, {NULL, NULL} }; static const luaL_Reg luv_tty_methods[] = { {"set_mode", luv_tty_set_mode}, {"get_winsize", luv_tty_get_winsize}, {NULL, NULL} }; static const luaL_Reg luv_udp_methods[] = { {"get_send_queue_size", luv_udp_get_send_queue_size}, {"get_send_queue_count", luv_udp_get_send_queue_count}, {"open", luv_udp_open}, {"bind", luv_udp_bind}, {"getsockname", luv_udp_getsockname}, {"set_membership", luv_udp_set_membership}, {"set_multicast_loop", luv_udp_set_multicast_loop}, {"set_multicast_ttl", luv_udp_set_multicast_ttl}, {"set_multicast_interface", luv_udp_set_multicast_interface}, {"set_broadcast", luv_udp_set_broadcast}, {"set_ttl", luv_udp_set_ttl}, {"send", luv_udp_send}, {"try_send", luv_udp_try_send}, {"recv_start", luv_udp_recv_start}, {"recv_stop", luv_udp_recv_stop}, #if LUV_UV_VERSION_GEQ(1, 27, 0) {"connect", luv_udp_connect}, {"getpeername", luv_udp_getpeername}, #endif {NULL, NULL} }; static const luaL_Reg luv_signal_methods[] = { {"start", luv_signal_start}, {"stop", luv_signal_stop}, {NULL, NULL} }; #if LUV_UV_VERSION_GEQ(1, 28, 0) static const luaL_Reg luv_dir_methods[] = { {"readdir", luv_fs_readdir}, {"closedir", luv_fs_closedir}, {NULL, NULL} }; static void luv_dir_init(lua_State* L) { luaL_newmetatable(L, "uv_dir"); lua_pushcfunction(L, luv_fs_dir_tostring); lua_setfield(L, -2, "__tostring"); lua_pushcfunction(L, luv_fs_dir_gc); lua_setfield(L, -2, "__gc"); luaL_newlib(L, luv_dir_methods); lua_setfield(L, -2, "__index"); lua_pop(L, 1); } #endif static void luv_handle_init(lua_State* L) { lua_newtable(L); #define XX(uc, lc) \ luaL_newmetatable (L, "uv_"#lc); \ lua_pushcfunction(L, luv_handle_tostring); \ lua_setfield(L, -2, "__tostring"); \ lua_pushcfunction(L, luv_handle_gc); \ lua_setfield(L, -2, "__gc"); \ luaL_newlib(L, luv_##lc##_methods); \ luaL_setfuncs(L, luv_handle_methods, 0); \ lua_setfield(L, -2, "__index"); \ lua_pushboolean(L, 1); \ lua_rawset(L, -3); UV_HANDLE_TYPE_MAP(XX) #undef XX lua_setfield(L, LUA_REGISTRYINDEX, "uv_handle"); lua_newtable(L); luaL_getmetatable(L, "uv_pipe"); lua_getfield(L, -1, "__index"); luaL_setfuncs(L, luv_stream_methods, 0); lua_pop(L, 1); lua_pushboolean(L, 1); lua_rawset(L, -3); luaL_getmetatable(L, "uv_tcp"); lua_getfield(L, -1, "__index"); luaL_setfuncs(L, luv_stream_methods, 0); lua_pop(L, 1); lua_pushboolean(L, 1); lua_rawset(L, -3); luaL_getmetatable(L, "uv_tty"); lua_getfield(L, -1, "__index"); luaL_setfuncs(L, luv_stream_methods, 0); lua_pop(L, 1); lua_pushboolean(L, 1); lua_rawset(L, -3); lua_setfield(L, LUA_REGISTRYINDEX, "uv_stream"); } // Call lua function, will pop nargs values from top of vm stack and push some // values according to nresults. When error occurs, it will print error message // to stderr, and memory allocation error will cause exit. LUALIB_API int luv_cfpcall(lua_State* L, int nargs, int nresult, int flags) { int ret, top, errfunc; // Get the traceback function in case of error if ((flags & (LUVF_CALLBACK_NOTRACEBACK|LUVF_CALLBACK_NOERRMSG) ) == 0) { lua_pushcfunction(L, luv_traceback); errfunc = lua_gettop(L); // And insert it before the function and args lua_insert(L, -2 - nargs); errfunc -= (nargs+1); }else errfunc = 0; top = lua_gettop(L); ret = lua_pcall(L, nargs, nresult, errfunc); switch (ret) { case LUA_OK: break; case LUA_ERRMEM: if ((flags & LUVF_CALLBACK_NOERRMSG) == 0) fprintf(stderr, "System Error: %s\n", lua_tostring(L, -1)); if ((flags & LUVF_CALLBACK_NOEXIT) == 0) exit(-1); lua_pop(L, 1); ret = -ret; break; case LUA_ERRRUN: case LUA_ERRERR: default: if ((flags & LUVF_CALLBACK_NOERRMSG) == 0) fprintf(stderr, "Uncaught Error: %s\n", lua_tostring(L, -1)); if ((flags & LUVF_CALLBACK_NOEXIT) == 0) exit(-1); lua_pop(L, 1); ret = -ret; break; } if ((flags & (LUVF_CALLBACK_NOTRACEBACK|LUVF_CALLBACK_NOERRMSG) ) == 0) { lua_remove(L, errfunc); } if (ret == LUA_OK) { if(nresult == LUA_MULTRET) nresult = lua_gettop(L) - top + nargs + 1; return nresult; } return ret; } // TODO: see if we can avoid using a string key for this to increase performance static const char* luv_ctx_key = "luv_context"; // Please look at luv_ctx_t in luv.h LUALIB_API luv_ctx_t* luv_context(lua_State* L) { luv_ctx_t* ctx; lua_pushstring(L, luv_ctx_key); lua_rawget(L, LUA_REGISTRYINDEX); if (lua_isnil(L, -1)) { // create it if not exist in registry lua_pushstring(L, luv_ctx_key); ctx = (luv_ctx_t*)lua_newuserdata(L, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); lua_rawset(L, LUA_REGISTRYINDEX); } else { ctx = (luv_ctx_t*)lua_touserdata(L, -1); } lua_pop(L, 1); return ctx; } LUALIB_API lua_State* luv_state(lua_State* L) { return luv_context(L)->L; } LUALIB_API uv_loop_t* luv_loop(lua_State* L) { return luv_context(L)->loop; } // Set an external loop, before luaopen_luv LUALIB_API void luv_set_loop(lua_State* L, uv_loop_t* loop) { luv_ctx_t* ctx = luv_context(L); ctx->loop = loop; ctx->L = L; } // Set an external event callback routine, before luaopen_luv LUALIB_API void luv_set_callback(lua_State* L, luv_CFpcall pcall) { luv_ctx_t* ctx = luv_context(L); ctx->pcall = pcall; } static void walk_cb(uv_handle_t *handle, void *arg) { (void)arg; if (!uv_is_closing(handle)) { uv_close(handle, luv_close_cb); } } static int loop_gc(lua_State *L) { luv_ctx_t *ctx = luv_context(L); uv_loop_t* loop = ctx->loop; if (loop==NULL) return 0; // Call uv_close on every active handle uv_walk(loop, walk_cb, NULL); // Run the event loop until all handles are successfully closed while (uv_loop_close(loop)) { uv_run(loop, UV_RUN_DEFAULT); } return 0; } LUALIB_API int luaopen_luv (lua_State* L) { luv_ctx_t* ctx = luv_context(L); luaL_newlib(L, luv_functions); // loop is NULL, luv need to create an inner loop if (ctx->loop==NULL) { int ret; uv_loop_t* loop; // Setup the uv_loop meta table for a proper __gc luaL_newmetatable(L, "uv_loop.meta"); lua_pushstring(L, "__gc"); lua_pushcfunction(L, loop_gc); lua_settable(L, -3); lua_pop(L, 1); lua_pushstring(L, "_loop"); loop = (uv_loop_t*)lua_newuserdata(L, sizeof(*loop)); // setup the userdata's metatable for __gc luaL_getmetatable(L, "uv_loop.meta"); lua_setmetatable(L, -2); // create a ref to loop, avoid __gc early // this puts the loop userdata into the _loop key // in the returned luv table lua_rawset(L, -3); ctx->loop = loop; ctx->L = L; ret = uv_loop_init(loop); if (ret < 0) { return luaL_error(L, "%s: %s\n", uv_err_name(ret), uv_strerror(ret)); } } // pcall is NULL, luv use default callback routine if (ctx->pcall==NULL) { ctx->pcall = luv_cfpcall; } luv_req_init(L); luv_handle_init(L); #if LUV_UV_VERSION_GEQ(1, 28, 0) luv_dir_init(L); #endif luv_thread_init(L); luv_work_init(L); luv_constants(L); lua_setfield(L, -2, "constants"); return 1; } luv-1.36.0-0/src/luv.h000066400000000000000000000102111364617304100143120ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LUV_H #define LUV_H #include #include #include #include "uv.h" #include #include #include #if defined(_WIN32) # include # include # include # ifndef __MINGW32__ # define S_ISREG(x) (((x) & _S_IFMT) == _S_IFREG) # define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR) # define S_ISFIFO(x) (((x) & _S_IFMT) == _S_IFIFO) # define S_ISCHR(x) (((x) & _S_IFMT) == _S_IFCHR) # define S_ISBLK(x) 0 # endif # define S_ISLNK(x) (((x) & S_IFLNK) == S_IFLNK) # define S_ISSOCK(x) 0 #else # include #endif #ifndef PATH_MAX #define PATH_MAX (8096) #endif #ifndef MAX_TITLE_LENGTH #define MAX_TITLE_LENGTH (8192) #endif // luv flags to control luv_CFpcall routine #define LUVF_CALLBACK_NOEXIT 0x01 // Don't exit when LUA_ERRMEM #define LUVF_CALLBACK_NOTRACEBACK 0x02 // Don't traceback when error #define LUVF_CALLBACK_NOERRMSG 0x04 // Don't output err message /* Prototype of external callback routine. * The caller and the implementer exchanges data by the lua vm stack. * The caller push a lua function and nargs values onto the stack, then call it. * The implementer remove nargs(argument)+1(function) values from vm stack, * push all returned values by lua function onto the stack, and return an * integer as result code. If the result >= 0, that means the number of * values leave on the stack, or the callback routine error, nothing leave on * the stack, -result is the error value returned by lua_pcall. * * When LUVF_CALLBACK_NOEXIT is set, the implementer should not exit. * When LUVF_CALLBACK_NOTRACEBACK is set, the implementer will not do traceback. * * Need to notice that the implementer must balance the lua vm stack, and maybe * exit when memory allocation error. */ typedef int (*luv_CFpcall) (lua_State* L, int nargs, int nresults, int flags); /* Default implemention of event callback */ LUALIB_API int luv_cfpcall(lua_State* L, int nargs, int nresult, int flags); typedef struct { uv_loop_t* loop; /* main loop */ lua_State* L; /* main thread,ensure coroutines works */ luv_CFpcall pcall; /* luv event callback function in protected mode */ void* extra; /* extra data */ } luv_ctx_t; /* Retrieve all the luv context from a lua_State */ LUALIB_API luv_ctx_t* luv_context(lua_State* L); /* Retrieve the main thread of the given lua_State */ LUALIB_API lua_State* luv_state(lua_State* L); /* Retrieve the uv_loop_t set for the given lua_State Note: Each lua_State can have a custom uv_loop_t */ LUALIB_API uv_loop_t* luv_loop(lua_State* L); /* Set or clear an external uv_loop_t in a lua_State When using a custom/external loop, this must be called before luaopen_luv (otherwise luv will create and use its own loop) */ LUALIB_API void luv_set_loop(lua_State* L, uv_loop_t* loop); /* Set or clear an external c routine for luv event callback When using a custom/external function, this must be called before luaopen_luv (otherwise luv will use the default callback function: luv_cfpcall) */ LUALIB_API void luv_set_callback(lua_State* L, luv_CFpcall pcall); /* This is the main hook to load the library. This can be called multiple times in a process as long as you use a different lua_State and thread for each. */ LUALIB_API int luaopen_luv (lua_State *L); typedef lua_State* (*luv_acquire_vm)(); typedef void (*luv_release_vm)(lua_State* L); LUALIB_API void luv_set_thread_cb(luv_acquire_vm acquire, luv_release_vm release); #endif luv-1.36.0-0/src/misc.c000066400000000000000000000465421364617304100144520ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "luv.h" #ifdef _WIN32 #include #endif static int luv_guess_handle(lua_State* L) { uv_file file = luaL_checkinteger(L, 1); switch (uv_guess_handle(file)) { #define XX(uc, lc) case UV_##uc: lua_pushstring(L, #lc); break; UV_HANDLE_TYPE_MAP(XX) #undef XX case UV_FILE: lua_pushstring(L, "file"); break; default: return 0; } return 1; } static int luv_version(lua_State* L) { lua_pushinteger(L, uv_version()); return 1; } static int luv_version_string(lua_State* L) { lua_pushstring(L, uv_version_string()); return 1; } // requires the value at idx to be a string or number static void luv_prep_buf(lua_State *L, int idx, uv_buf_t *pbuf) { size_t len; // note: if the value is a number, lua_tolstring converts the stack value to a string pbuf->base = (char*)lua_tolstring(L, idx, &len); pbuf->len = len; } // - number of buffers is stored in *count // - if refs is non-NULL, then *refs is set to a heap-allocated, LUA_NOREF-terminated array // of ref integers (refs are to each string in the bufs) // returns: heap-allocated array of uv_buf_t static uv_buf_t* luv_prep_bufs(lua_State* L, int index, size_t *count, int **refs) { uv_buf_t *bufs; size_t i; *count = lua_rawlen(L, index); bufs = (uv_buf_t*)malloc(sizeof(uv_buf_t) * *count); int *refs_array = NULL; if (refs) refs_array = (int*)malloc(sizeof(int) * (*count + 1)); for (i = 0; i < *count; ++i) { lua_rawgeti(L, index, i + 1); if (!lua_isstring(L, -1)) { luaL_argerror(L, index, lua_pushfstring(L, "expected table of strings, found %s in the table", luaL_typename(L, -1))); return NULL; } luv_prep_buf(L, -1, &bufs[i]); if (refs) { // push the string again to ref it, will be popped by luaL_ref lua_pushvalue(L, -1); refs_array[i] = luaL_ref(L, LUA_REGISTRYINDEX); } lua_pop(L, 1); } if (refs) { // refs array is LUA_NOREF-terminated refs_array[*count] = LUA_NOREF; *refs = refs_array; } return bufs; } // Sets up a uv_bufs_t array to pass to write/send libuv functions that take a uv_buf_t* // - count: set to length of the returned uv_buf_t array // - req_data: refs to the strings used are stored in req_data->data/req_data->data_ref // returns: heap-allocated array of uv_buf_t static uv_buf_t* luv_check_bufs(lua_State* L, int index, size_t* count, luv_req_t* req_data) { uv_buf_t* bufs = NULL; if (lua_istable(L, index)) { int* refs = NULL; bufs = luv_prep_bufs(L, index, count, &refs); req_data->data = refs; req_data->data_ref = LUV_REQ_MULTIREF; } else if (lua_isstring(L, index)) { *count = 1; bufs = (uv_buf_t*)malloc(sizeof(uv_buf_t)); luv_prep_buf(L, index, bufs); lua_pushvalue(L, index); req_data->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); } else { luaL_argerror(L, index, lua_pushfstring(L, "data must be string or table of strings, got %s", luaL_typename(L, index))); } return bufs; } // Like luv_check_bufs but does not ref the buf strings. // Only meant to be used for functions like luv_udp_try_send. static uv_buf_t* luv_check_bufs_noref(lua_State* L, int index, size_t* count) { uv_buf_t* bufs = NULL; if (lua_istable(L, index)) { bufs = luv_prep_bufs(L, index, count, NULL); } else if (lua_isstring(L, index)) { *count = 1; bufs = (uv_buf_t*)malloc(sizeof(uv_buf_t)); luv_prep_buf(L, index, bufs); } else { luaL_argerror(L, index, lua_pushfstring(L, "data must be string or table of strings, got %s", luaL_typename(L, index))); } return bufs; } static int luv_get_process_title(lua_State* L) { char title[MAX_TITLE_LENGTH]; int ret = uv_get_process_title(title, MAX_TITLE_LENGTH); if (ret < 0) return luv_error(L, ret); lua_pushstring(L, title); return 1; } static int luv_set_process_title(lua_State* L) { const char* title = luaL_checkstring(L, 1); int ret = uv_set_process_title(title); return luv_result(L, ret); } static int luv_resident_set_memory(lua_State* L) { size_t rss; int ret = uv_resident_set_memory(&rss); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, rss); return 1; } static int luv_uptime(lua_State* L) { double uptime; int ret = uv_uptime(&uptime); if (ret < 0) return luv_error(L, ret); lua_pushnumber(L, uptime); return 1; } static void luv_push_timeval_table(lua_State* L, const uv_timeval_t* t) { lua_createtable(L, 0, 2); lua_pushinteger(L, t->tv_sec); lua_setfield(L, -2, "sec"); lua_pushinteger(L, t->tv_usec); lua_setfield(L, -2, "usec"); } static int luv_getrusage(lua_State* L) { uv_rusage_t rusage; int ret = uv_getrusage(&rusage); if (ret < 0) return luv_error(L, ret); lua_createtable(L, 0, 16); // user CPU time used luv_push_timeval_table(L, &rusage.ru_utime); lua_setfield(L, -2, "utime"); // system CPU time used luv_push_timeval_table(L, &rusage.ru_stime); lua_setfield(L, -2, "stime"); // maximum resident set size lua_pushinteger(L, rusage.ru_maxrss); lua_setfield(L, -2, "maxrss"); // integral shared memory size lua_pushinteger(L, rusage.ru_ixrss); lua_setfield(L, -2, "ixrss"); // integral unshared data size lua_pushinteger(L, rusage.ru_idrss); lua_setfield(L, -2, "idrss"); // integral unshared stack size lua_pushinteger(L, rusage.ru_isrss); lua_setfield(L, -2, "isrss"); // page reclaims (soft page faults) lua_pushinteger(L, rusage.ru_minflt); lua_setfield(L, -2, "minflt"); // page faults (hard page faults) lua_pushinteger(L, rusage.ru_majflt); lua_setfield(L, -2, "majflt"); // swaps lua_pushinteger(L, rusage.ru_nswap); lua_setfield(L, -2, "nswap"); // block input operations lua_pushinteger(L, rusage.ru_inblock); lua_setfield(L, -2, "inblock"); // block output operations lua_pushinteger(L, rusage.ru_oublock); lua_setfield(L, -2, "oublock"); // IPC messages sent lua_pushinteger(L, rusage.ru_msgsnd); lua_setfield(L, -2, "msgsnd"); // IPC messages received lua_pushinteger(L, rusage.ru_msgrcv); lua_setfield(L, -2, "msgrcv"); // signals received lua_pushinteger(L, rusage.ru_nsignals); lua_setfield(L, -2, "nsignals"); // voluntary context switches lua_pushinteger(L, rusage.ru_nvcsw); lua_setfield(L, -2, "nvcsw"); // involuntary context switches lua_pushinteger(L, rusage.ru_nivcsw); lua_setfield(L, -2, "nivcsw"); return 1; } static int luv_cpu_info(lua_State* L) { uv_cpu_info_t* cpu_infos; int count, i; int ret = uv_cpu_info(&cpu_infos, &count); if (ret < 0) return luv_error(L, ret); lua_newtable(L); for (i = 0; i < count; i++) { lua_newtable(L); lua_pushstring(L, cpu_infos[i].model); lua_setfield(L, -2, "model"); lua_pushnumber(L, cpu_infos[i].speed); lua_setfield(L, -2, "speed"); lua_newtable(L); lua_pushnumber(L, cpu_infos[i].cpu_times.user); lua_setfield(L, -2, "user"); lua_pushnumber(L, cpu_infos[i].cpu_times.nice); lua_setfield(L, -2, "nice"); lua_pushnumber(L, cpu_infos[i].cpu_times.sys); lua_setfield(L, -2, "sys"); lua_pushnumber(L, cpu_infos[i].cpu_times.idle); lua_setfield(L, -2, "idle"); lua_pushnumber(L, cpu_infos[i].cpu_times.irq); lua_setfield(L, -2, "irq"); lua_setfield(L, -2, "times"); lua_rawseti(L, -2, i + 1); } uv_free_cpu_info(cpu_infos, count); return 1; } static int luv_interface_addresses(lua_State* L) { uv_interface_address_t* interfaces; int count, i; char ip[INET6_ADDRSTRLEN]; char netmask[INET6_ADDRSTRLEN]; uv_interface_addresses(&interfaces, &count); lua_newtable(L); for (i = 0; i < count; i++) { lua_getfield(L, -1, interfaces[i].name); if (!lua_istable(L, -1)) { lua_pop(L, 1); lua_newtable(L); lua_pushvalue(L, -1); lua_setfield(L, -3, interfaces[i].name); } lua_newtable(L); lua_pushboolean(L, interfaces[i].is_internal); lua_setfield(L, -2, "internal"); lua_pushlstring(L, interfaces[i].phys_addr, sizeof(interfaces[i].phys_addr)); lua_setfield(L, -2, "mac"); if (interfaces[i].address.address4.sin_family == AF_INET) { uv_ip4_name(&interfaces[i].address.address4, ip, sizeof(ip)); uv_ip4_name(&interfaces[i].netmask.netmask4, netmask, sizeof(netmask)); } else if (interfaces[i].address.address4.sin_family == AF_INET6) { uv_ip6_name(&interfaces[i].address.address6, ip, sizeof(ip)); uv_ip6_name(&interfaces[i].netmask.netmask6, netmask, sizeof(netmask)); } else { strncpy(ip, "", INET6_ADDRSTRLEN); strncpy(netmask, "", INET6_ADDRSTRLEN); } lua_pushstring(L, ip); lua_setfield(L, -2, "ip"); lua_pushstring(L, netmask); lua_setfield(L, -2, "netmask"); lua_pushstring(L, luv_af_num_to_string(interfaces[i].address.address4.sin_family)); lua_setfield(L, -2, "family"); lua_rawseti(L, -2, lua_rawlen (L, -2) + 1); lua_pop(L, 1); } uv_free_interface_addresses(interfaces, count); return 1; } static int luv_loadavg(lua_State* L) { double avg[3]; uv_loadavg(avg); lua_pushnumber(L, avg[0]); lua_pushnumber(L, avg[1]); lua_pushnumber(L, avg[2]); return 3; } static int luv_exepath(lua_State* L) { size_t size = 2*PATH_MAX; char exe_path[2*PATH_MAX]; int ret = uv_exepath(exe_path, &size); if (ret < 0) return luv_error(L, ret); lua_pushlstring(L, exe_path, size); return 1; } static int luv_cwd(lua_State* L) { size_t size = 2*PATH_MAX; char path[2*PATH_MAX]; int ret = uv_cwd(path, &size); if (ret < 0) return luv_error(L, ret); lua_pushlstring(L, path, size); return 1; } static int luv_chdir(lua_State* L) { int ret = uv_chdir(luaL_checkstring(L, 1)); return luv_result(L, ret); } #if LUV_UV_VERSION_GEQ(1, 9, 0) static int luv_os_tmpdir(lua_State* L) { size_t size = 2*PATH_MAX; char tmpdir[2*PATH_MAX]; int ret = uv_os_tmpdir(tmpdir, &size); if (ret < 0) return luv_error(L, ret); lua_pushlstring(L, tmpdir, size); return 1; } static int luv_os_homedir(lua_State* L) { size_t size = 2*PATH_MAX; char homedir[2*PATH_MAX]; int ret = uv_os_homedir(homedir, &size); if (ret < 0) return luv_error(L, ret); lua_pushlstring(L, homedir, size); return 1; } static int luv_os_get_passwd(lua_State* L) { uv_passwd_t pwd; int ret = uv_os_get_passwd(&pwd); if (ret < 0) return luv_error(L, ret); lua_newtable(L); if (pwd.username) { lua_pushstring(L, pwd.username); lua_setfield(L, -2, "username"); } if (pwd.uid >= 0) { lua_pushinteger(L, pwd.uid); lua_setfield(L, -2, "uid"); } if (pwd.gid >= 0) { lua_pushinteger(L, pwd.gid); lua_setfield(L, -2, "gid"); } if (pwd.shell) { lua_pushstring(L, pwd.shell); lua_setfield(L, -2, "shell"); } if (pwd.homedir) { lua_pushstring(L, pwd.homedir); lua_setfield(L, -2, "homedir"); } uv_os_free_passwd(&pwd); return 1; } #endif #if LUV_UV_VERSION_GEQ(1, 29, 0) static int luv_get_constrained_memory(lua_State* L) { lua_pushnumber(L, uv_get_constrained_memory()); return 1; } #endif static int luv_get_total_memory(lua_State* L) { lua_pushnumber(L, uv_get_total_memory()); return 1; } static int luv_get_free_memory(lua_State* L) { lua_pushnumber(L, uv_get_free_memory()); return 1; } static int luv_hrtime(lua_State* L) { lua_pushnumber(L, uv_hrtime()); return 1; } static int luv_getpid(lua_State* L){ int pid = getpid(); lua_pushinteger(L, pid); return 1; } #ifndef _WIN32 static int luv_getuid(lua_State* L){ int uid = getuid(); lua_pushinteger(L, uid); return 1; } static int luv_getgid(lua_State* L){ int gid = getgid(); lua_pushinteger(L, gid); return 1; } static int luv_setuid(lua_State* L){ int uid = luaL_checkinteger(L, 1); int r = setuid(uid); if (-1 == r) { luaL_error(L, "Error setting UID"); } return 0; } static int luv_setgid(lua_State* L){ int gid = luaL_checkinteger(L, 1); int r = setgid(gid); if (-1 == r) { luaL_error(L, "Error setting GID"); } return 0; } #if LUV_UV_VERSION_GEQ(1, 8, 0) static int luv_print_all_handles(lua_State* L){ luv_ctx_t* ctx = luv_context(L); uv_print_all_handles(ctx->loop, stderr); return 0; } static int luv_print_active_handles(lua_State* L){ luv_ctx_t* ctx = luv_context(L); uv_print_active_handles(ctx->loop, stderr); return 0; } #endif #endif #if LUV_UV_VERSION_GEQ(1, 12, 0) static int luv_os_getenv(lua_State* L) { const char* name = luaL_checkstring(L, 1); size_t size = luaL_optinteger(L, 2, LUAL_BUFFERSIZE); char *buff = malloc(size); int ret = uv_os_getenv(name, buff, &size); if (ret == 0) { lua_pushlstring(L, buff, size); ret = 1; } else ret = luv_error(L, ret); free(buff); return ret; } static int luv_os_setenv(lua_State* L) { const char* name = luaL_checkstring(L, 1); const char* value = luaL_checkstring(L, 2); int ret = uv_os_setenv(name, value); if (ret == 0) lua_pushboolean(L, 1); else return luv_error(L, ret); return 1; } static int luv_os_unsetenv(lua_State* L) { const char* name = luaL_checkstring(L, 1); int ret = uv_os_unsetenv(name); if (ret == 0) lua_pushboolean(L, 1); else return luv_error(L, ret); return 1; } static int luv_os_gethostname(lua_State* L) { #if LUV_UV_VERSION_GEQ(1, 26, 0) char hostname[UV_MAXHOSTNAMESIZE]; #else char hostname[PATH_MAX]; #endif size_t size = sizeof(hostname); int ret = uv_os_gethostname(hostname, &size); if (ret == 0) { lua_pushlstring(L, hostname, size); ret = 1; } else ret = luv_error(L, ret); return ret; } #endif #if LUV_UV_VERSION_GEQ(1, 16, 0) static int luv_if_indextoname(lua_State* L) { /* 40 bytes address, 16 bytes device name, plus reserve. */ char scoped_addr[128]; size_t scoped_addr_len = sizeof(scoped_addr); unsigned int ifindex = (unsigned int)luaL_checkinteger(L, 1); int ret = uv_if_indextoname(ifindex - 1, scoped_addr, &scoped_addr_len); if (ret == 0) { lua_pushlstring(L, scoped_addr, scoped_addr_len); ret = 1; } else ret = luv_error(L, ret); return ret; } static int luv_if_indextoiid(lua_State* L) { char interface_id[UV_IF_NAMESIZE]; size_t interface_id_len = sizeof(interface_id); unsigned int ifindex = (unsigned int)luaL_checkinteger(L, 1); int ret = uv_if_indextoiid(ifindex - 1, interface_id, &interface_id_len); if (ret == 0) { lua_pushlstring(L, interface_id, interface_id_len); ret = 1; } else ret = luv_error(L, ret); return ret; } static int luv_os_getppid(lua_State* L) { lua_pushnumber(L, uv_os_getppid()); return 1; } #endif #if LUV_UV_VERSION_GEQ(1, 18, 0) static int luv_os_getpid(lua_State* L) { lua_pushnumber(L, uv_os_getpid()); return 1; } #endif #if LUV_UV_VERSION_GEQ(1, 23, 0) static int luv_os_getpriority(lua_State* L) { int priority; uv_pid_t pid = luaL_checkinteger(L, 1); int ret = uv_os_getpriority(pid, &priority); if (ret == 0) { lua_pushnumber(L, priority); ret = 1; } else { ret = luv_error(L, ret); } return ret; } #endif #if LUV_UV_VERSION_GEQ(1, 23, 0) static int luv_os_setpriority(lua_State* L) { uv_pid_t pid = luaL_checkinteger(L, 1); int priority= luaL_checkinteger(L, 2); int ret = uv_os_setpriority(pid, priority); if (ret == 0) { lua_pushboolean(L, 1); ret = 1; } else ret = luv_error(L, ret); return ret; } #endif #if LUV_UV_VERSION_GEQ(1, 25, 0) static int luv_os_uname(lua_State* L) { uv_utsname_t uname; int ret = uv_os_uname(&uname); if (ret == 0) { lua_newtable(L); lua_pushstring(L, uname.sysname); lua_setfield(L, -2, "sysname"); lua_pushstring(L, uname.release); lua_setfield(L, -2, "release"); lua_pushstring(L, uname.version); lua_setfield(L, -2, "version"); lua_pushstring(L, uname.machine); lua_setfield(L, -2, "machine"); ret = 1; } else ret = luv_error(L, ret); return ret; } #endif #if LUV_UV_VERSION_GEQ(1, 28, 0) static int luv_gettimeofday(lua_State* L) { uv_timeval64_t tv = { 0 }; int ret = uv_gettimeofday(&tv); if (ret == 0) { #if defined(__LP64__) lua_pushinteger(L, tv.tv_sec); #else lua_pushnumber(L, tv.tv_sec); #endif lua_pushinteger(L, tv.tv_usec); return 2; } else ret = luv_error(L, ret); return ret; } #endif #if LUV_UV_VERSION_GEQ(1, 31, 0) static int luv_os_environ(lua_State* L) { int i, ret, envcount; uv_env_item_t* envitems; ret = uv_os_environ(&envitems, &envcount); if (ret==0) { lua_newtable(L); for(i=0; idata; lua_State* L = data->ctx->L; int nargs; if (status < 0) { luv_status(L, status); nargs = 1; } else { lua_pushnil(L); lua_pushlstring(L, (const char*)buf, buflen); nargs = 2; } luv_fulfill_req(L, (luv_req_t*)req->data, nargs); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; } static int luv_random(lua_State* L) { luv_ctx_t* ctx = luv_context(L); size_t buflen = (size_t)luaL_checkinteger(L, 1); // this is duplication of code in LibUV but since we need to try allocating the memory // before calling uv_random, we need to do this check ahead-of-time if (buflen > 0x7FFFFFFFu) { return luv_error(L, UV_E2BIG); } // flags param can be nil, an integer, or a table unsigned int flags = 0; if (lua_type(L, 2) == LUA_TNUMBER || lua_isnoneornil(L, 2)) { flags = (unsigned int)luaL_optinteger(L, 2, 0); } else if (lua_type(L, 2) == LUA_TTABLE) { // this is for forwards-compatibility: if flags ever get added, // we want to be able to take a table } else { return luaL_argerror(L, 2, "expected nil, integer, or table"); } int cb_ref = luv_check_continuation(L, 3); int sync = cb_ref == LUA_NOREF; void* buf = lua_newuserdata(L, buflen); if (sync) { // sync version doesn't need anything except buf, buflen, and flags int ret = uv_random(NULL, NULL, buf, buflen, flags, NULL); if (ret < 0) { return luv_error(L, ret); } lua_pushlstring(L, (const char*)buf, buflen); return 1; } else { // ref buffer int buf_ref = luaL_ref(L, LUA_REGISTRYINDEX); uv_random_t* req = (uv_random_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, cb_ref); ((luv_req_t*)req->data)->req_ref = buf_ref; int ret = uv_random(ctx->loop, req, buf, buflen, flags, luv_random_cb); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } return luv_result(L, ret); } } #endif luv-1.36.0-0/src/pipe.c000066400000000000000000000065111364617304100144440ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_pipe_t* luv_check_pipe(lua_State* L, int index) { uv_pipe_t* handle = (uv_pipe_t*)luv_checkudata(L, index, "uv_pipe"); luaL_argcheck(L, handle->type == UV_NAMED_PIPE && handle->data, index, "Expected uv_pipe_t"); return handle; } static int luv_new_pipe(lua_State* L) { uv_pipe_t* handle; int ipc, ret; luv_ctx_t* ctx = luv_context(L); ipc = luv_optboolean(L, 1, 0); handle = (uv_pipe_t*)luv_newuserdata(L, sizeof(*handle)); ret = uv_pipe_init(ctx->loop, handle, ipc); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static int luv_pipe_open(lua_State* L) { uv_pipe_t* handle = luv_check_pipe(L, 1); uv_file file = luaL_checkinteger(L, 2); int ret = uv_pipe_open(handle, file); return luv_result(L, ret); } static int luv_pipe_bind(lua_State* L) { uv_pipe_t* handle = luv_check_pipe(L, 1); const char* name = luaL_checkstring(L, 2); int ret = uv_pipe_bind(handle, name); return luv_result(L, ret); } static int luv_pipe_connect(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_pipe_t* handle = luv_check_pipe(L, 1); const char* name = luaL_checkstring(L, 2); int ref = luv_check_continuation(L, 3); uv_connect_t* req = (uv_connect_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); uv_pipe_connect(req, handle, name, luv_connect_cb); return 1; } static int luv_pipe_getsockname(lua_State* L) { uv_pipe_t* handle = luv_check_pipe(L, 1); size_t len = 2*PATH_MAX; char buf[2*PATH_MAX]; int ret = uv_pipe_getsockname(handle, buf, &len); if (ret < 0) return luv_error(L, ret); lua_pushlstring(L, buf, len); return 1; } #if LUV_UV_VERSION_GEQ(1, 3, 0) static int luv_pipe_getpeername(lua_State* L) { uv_pipe_t* handle = luv_check_pipe(L, 1); size_t len = 2*PATH_MAX; char buf[2*PATH_MAX]; int ret = uv_pipe_getpeername(handle, buf, &len); if (ret < 0) return luv_error(L, ret); lua_pushlstring(L, buf, len); return 1; } #endif static int luv_pipe_pending_instances(lua_State* L) { uv_pipe_t* handle = luv_check_pipe(L, 1); int count = luaL_checkinteger(L, 2); uv_pipe_pending_instances(handle, count); return 0; } static int luv_pipe_pending_count(lua_State* L) { uv_pipe_t* handle = luv_check_pipe(L, 1); lua_pushinteger(L, uv_pipe_pending_count(handle)); return 1; } static int luv_pipe_pending_type(lua_State* L) { uv_pipe_t* handle = luv_check_pipe(L, 1); uv_handle_type type = uv_pipe_pending_type(handle); const char* type_name; switch (type) { #define XX(uc, lc) \ case UV_##uc: type_name = #lc; break; UV_HANDLE_TYPE_MAP(XX) #undef XX default: return 0; } lua_pushstring(L, type_name); return 1; } luv-1.36.0-0/src/poll.c000066400000000000000000000112671364617304100144610ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_poll_t* luv_check_poll(lua_State* L, int index) { uv_poll_t* handle = (uv_poll_t*)luv_checkudata(L, index, "uv_poll"); luaL_argcheck(L, handle->type == UV_POLL && handle->data, index, "Expected uv_poll_t"); return handle; } static int luv_new_poll(lua_State* L) { luv_ctx_t* ctx = luv_context(L); int fd = luaL_checkinteger(L, 1); uv_poll_t* handle = (uv_poll_t*)luv_newuserdata(L, sizeof(*handle)); int ret = uv_poll_init(ctx->loop, handle, fd); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static int luv_new_socket_poll(lua_State* L) { luv_ctx_t* ctx = luv_context(L); int fd = luaL_checkinteger(L, 1); uv_poll_t* handle = (uv_poll_t*)luv_newuserdata(L, sizeof(*handle)); int ret = uv_poll_init_socket(ctx->loop, handle, fd); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static const char *const luv_pollevents[] = { "r", "w", "rw", #if LUV_UV_VERSION_GEQ(1, 9, 0) "d", "rd", "wd", "rwd", #endif #if LUV_UV_VERSION_GEQ(1, 14, 0) "p", "rp", "wp", "rwp", "dp", "rdp", "wdp", "rwdp", #endif NULL }; static void luv_poll_cb(uv_poll_t* handle, int status, int events) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; const char* evtstr; if (status < 0) { fprintf(stderr, "%s: %s\n", uv_err_name(status), uv_strerror(status)); lua_pushstring(L, uv_err_name(status)); } else { lua_pushnil(L); } switch (events) { case UV_READABLE: evtstr = "r"; break; case UV_WRITABLE: evtstr = "w"; break; case UV_READABLE|UV_WRITABLE: evtstr = "rw"; break; #if LUV_UV_VERSION_GEQ(1, 9, 0) case UV_DISCONNECT: evtstr = "d"; break; case UV_READABLE|UV_DISCONNECT: evtstr = "rd"; break; case UV_WRITABLE|UV_DISCONNECT: evtstr = "wd"; break; case UV_READABLE|UV_WRITABLE|UV_DISCONNECT: evtstr = "rwd"; break; #endif #if LUV_UV_VERSION_GEQ(1, 14, 0) case UV_PRIORITIZED: evtstr = "p"; break; case UV_READABLE|UV_PRIORITIZED: evtstr = "rp"; break; case UV_WRITABLE|UV_PRIORITIZED: evtstr = "wp"; break; case UV_READABLE|UV_WRITABLE|UV_PRIORITIZED: evtstr = "rwp"; break; case UV_DISCONNECT|UV_PRIORITIZED: evtstr = "dp"; break; case UV_READABLE|UV_DISCONNECT|UV_PRIORITIZED: evtstr = "rdp"; break; case UV_WRITABLE|UV_DISCONNECT|UV_PRIORITIZED: evtstr = "wdp"; break; case UV_READABLE|UV_WRITABLE|UV_DISCONNECT|UV_PRIORITIZED: evtstr = "rwdp"; break; #endif default: evtstr = ""; break; } lua_pushstring(L, evtstr); luv_call_callback(L, data, LUV_POLL, 2); } static int luv_poll_start(lua_State* L) { uv_poll_t* handle = luv_check_poll(L, 1); int events, ret; switch (luaL_checkoption(L, 2, "rw", luv_pollevents)) { case 0: events = UV_READABLE; break; case 1: events = UV_WRITABLE; break; case 2: events = UV_READABLE | UV_WRITABLE; break; #if LUV_UV_VERSION_GEQ(1, 9, 0) case 3: events = UV_DISCONNECT; break; case 4: events = UV_READABLE|UV_DISCONNECT; break; case 5: events = UV_WRITABLE|UV_DISCONNECT; break; case 6: events = UV_READABLE|UV_WRITABLE|UV_DISCONNECT; break; #endif #if LUV_UV_VERSION_GEQ(1, 14, 0) case 7: events = UV_PRIORITIZED; break; case 8: events = UV_READABLE|UV_PRIORITIZED; break; case 9: events = UV_WRITABLE|UV_PRIORITIZED; break; case 10: events = UV_READABLE|UV_WRITABLE|UV_PRIORITIZED; break; case 11: events = UV_DISCONNECT|UV_PRIORITIZED; break; case 12: events = UV_READABLE|UV_DISCONNECT|UV_PRIORITIZED; break; case 13: events = UV_WRITABLE|UV_DISCONNECT|UV_PRIORITIZED; break; case 14: events = UV_READABLE|UV_WRITABLE|UV_DISCONNECT|UV_PRIORITIZED; break; #endif default: events = 0; /* unreachable */ } luv_check_callback(L, (luv_handle_t*)handle->data, LUV_POLL, 3); ret = uv_poll_start(handle, events, luv_poll_cb); return luv_result(L, ret); } static int luv_poll_stop(lua_State* L) { uv_poll_t* handle = luv_check_poll(L, 1); int ret = uv_poll_stop(handle); return luv_result(L, ret); } luv-1.36.0-0/src/prepare.c000066400000000000000000000034771364617304100151550ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_prepare_t* luv_check_prepare(lua_State* L, int index) { uv_prepare_t* handle = (uv_prepare_t*)luv_checkudata(L, index, "uv_prepare"); luaL_argcheck(L, handle->type == UV_PREPARE && handle->data, index, "Expected uv_prepare_t"); return handle; } static int luv_new_prepare(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_prepare_t* handle = (uv_prepare_t*)luv_newuserdata(L, sizeof(*handle)); int ret = uv_prepare_init(ctx->loop, handle); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static void luv_prepare_cb(uv_prepare_t* handle) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; luv_call_callback(L, data, LUV_PREPARE, 0); } static int luv_prepare_start(lua_State* L) { uv_prepare_t* handle = luv_check_prepare(L, 1); int ret; luv_check_callback(L, (luv_handle_t*)handle->data, LUV_PREPARE, 2); ret = uv_prepare_start(handle, luv_prepare_cb); return luv_result(L, ret); } static int luv_prepare_stop(lua_State* L) { uv_prepare_t* handle = luv_check_prepare(L, 1); int ret = uv_prepare_stop(handle); return luv_result(L, ret); } luv-1.36.0-0/src/private.h000066400000000000000000000104511364617304100151640ustar00rootroot00000000000000#ifndef LUV_PRIVATE_H #define LUV_PRIVATE_H #include #if (LUA_VERSION_NUM != 503) #include "compat-5.3.h" #endif #include "luv.h" #include "util.h" #include "lhandle.h" #include "lreq.h" #include "lthreadpool.h" #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" #endif /* From stream.c */ static uv_stream_t* luv_check_stream(lua_State* L, int index); static void luv_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); /* From lhandle.c */ /* Traceback for lua_pcall */ static int luv_traceback (lua_State *L); /* Setup the handle at the top of the stack */ static luv_handle_t* luv_setup_handle(lua_State* L, luv_ctx_t* ctx); /* Store a lua callback in a luv_handle for future callbacks. Either replace an existing callback by id or append a new one at the end. */ static void luv_check_callback(lua_State* L, luv_handle_t* data, luv_callback_id id, int index); /* Lookup a function and call it with nargs If there is no such function, pop the args. */ static void luv_call_callback(lua_State* L, luv_handle_t* data, luv_callback_id id, int nargs); /* Push a userdata on the stack from a handle */ static void luv_find_handle(lua_State* L, luv_handle_t* data); /* Unref the handle from the lua world, allowing it to GC */ static void luv_unref_handle(lua_State* L, luv_handle_t* data); /* From lreq.c */ /* Used in the top of a setup function to check the arg and ref the callback to an integer. */ static int luv_check_continuation(lua_State* L, int index); /* setup a luv_req_t. The userdata is assumed to be at the top of the stack. */ static luv_req_t* luv_setup_req(lua_State* L, luv_ctx_t* ctx, int ref); static void luv_fulfill_req(lua_State* L, luv_req_t* data, int nargs); static void luv_cleanup_req(lua_State* L, luv_req_t* data); /* From handle.c */ static void* luv_checkudata(lua_State* L, int ud, const char* tname); static void* luv_newuserdata(lua_State* L, size_t sz); /* From misc.c */ static void luv_prep_buf(lua_State *L, int idx, uv_buf_t *pbuf); static uv_buf_t* luv_prep_bufs(lua_State* L, int index, size_t *count, int **refs); static uv_buf_t* luv_check_bufs(lua_State* L, int index, size_t *count, luv_req_t* req_data); static uv_buf_t* luv_check_bufs_noref(lua_State* L, int index, size_t *count); /* From tcp.c */ static void parse_sockaddr(lua_State* L, struct sockaddr_storage* address); static void luv_connect_cb(uv_connect_t* req, int status); /* From fs.c */ static void luv_push_stats_table(lua_State* L, const uv_stat_t* s); /* From constants.c */ static int luv_af_string_to_num(const char* string); static const char* luv_af_num_to_string(const int num); static int luv_sock_string_to_num(const char* string); static const char* luv_sock_num_to_string(const int num); static int luv_sig_string_to_num(const char* string); static const char* luv_sig_num_to_string(const int num); /* From util.c */ // Push a Libuv error code onto the Lua stack static int luv_error(lua_State* L, int status); // Common error handling pattern for binding uv functions that only return success/error. // If the binding returns a value other than success/error, this function should not be used. static int luv_result(lua_State* L, int status); // Push the error name onto the stack if status is an error code, // or push nil onto the stack if it's not an error code static void luv_status(lua_State* L, int status); // Return true if the object is a function or a callable table static int luv_is_callable(lua_State* L, int index); // Check if the argument is callable and throw an error if it's not static void luv_check_callable(lua_State* L, int index); static int luv_optboolean(lua_State*L, int idx, int defaultval); /* From thread.c */ static lua_State* luv_thread_acquire_vm(); /* From work.c */ static const char* luv_thread_dumped(lua_State* L, int idx, size_t* l); static const char* luv_getmtname(lua_State *L, int idx); static int luv_thread_arg_set(lua_State* L, luv_thread_arg_t* args, int idx, int top, int flags); static int luv_thread_arg_push(lua_State* L, luv_thread_arg_t* args, int flags); static void luv_thread_arg_clear(lua_State* L, luv_thread_arg_t* args, int flags); static luv_acquire_vm acquire_vm_cb = NULL; static luv_release_vm release_vm_cb = NULL; #if defined(__clang__) #pragma clang diagnostic pop #endif #endif luv-1.36.0-0/src/process.c000066400000000000000000000214231364617304100151640ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" #include static int luv_disable_stdio_inheritance(lua_State* L) { (void)L; uv_disable_stdio_inheritance(); return 0; } static uv_process_t* luv_check_process(lua_State* L, int index) { uv_process_t* handle = (uv_process_t*)luv_checkudata(L, index, "uv_process"); luaL_argcheck(L, handle->type == UV_PROCESS && handle->data, index, "Expected uv_process_t"); return handle; } static void exit_cb(uv_process_t* handle, int64_t exit_status, int term_signal) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; lua_pushinteger(L, exit_status); lua_pushinteger(L, term_signal); luv_call_callback(L, data, LUV_EXIT, 2); } static void luv_spawn_close_cb(uv_handle_t* handle) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; luv_unref_handle(L, (luv_handle_t*)handle->data); } static void luv_clean_options(uv_process_options_t* options) { free(options->args); free(options->stdio); free(options->env); } // iterates over the tbl to find the max integer // key of the table that is >= 1. If any key is // NOT an integer, simply call lua_rawlen(). static int sparse_rawlen(lua_State* L, int tbl) { int len = 0; tbl = lua_absindex(L, tbl); lua_pushnil(L); while (lua_next(L, -2)) { if (lua_type(L, -2) == LUA_TNUMBER) { int idx = lua_tonumber(L, -2); if (floor(idx) == idx && idx >= 1) { if (idx > len) len = idx; lua_pop(L, 1); continue; } } lua_pop(L, 2); return lua_rawlen(L, tbl); } return len; } static int luv_spawn(lua_State* L) { uv_process_t* handle; uv_process_options_t options; size_t i, len = 0; int ret; luv_ctx_t* ctx = luv_context(L); memset(&options, 0, sizeof(options)); options.exit_cb = exit_cb; options.file = luaL_checkstring(L, 1); options.flags = 0; // Make sure the 2nd argument is a table luaL_checktype(L, 2, LUA_TTABLE); // get the args list lua_getfield(L, 2, "args"); // +1 for inserted command at front if (lua_type(L, -1) == LUA_TTABLE) { len = 1 + lua_rawlen(L, -1); } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 3, "args option must be table"); } else { len = 1; } // +1 for null terminator at end options.args = (char**)malloc((len + 1) * sizeof(*options.args)); if (!options.args) { luv_clean_options(&options); return luaL_error(L, "Problem allocating args"); } options.args[0] = (char*)options.file; for (i = 1; i < len; ++i) { lua_rawgeti(L, -1, i); options.args[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } options.args[len] = NULL; lua_pop(L, 1); // get the stdio list lua_getfield(L, 2, "stdio"); if (lua_type(L, -1) == LUA_TTABLE) { options.stdio_count = len = sparse_rawlen(L, -1); options.stdio = (uv_stdio_container_t*)malloc(len * sizeof(*options.stdio)); if (!options.stdio) { luv_clean_options(&options); return luaL_error(L, "Problem allocating stdio"); } for (i = 0; i < len; ++i) { lua_rawgeti(L, -1, i + 1); // integers are assumed to be file descripters if (lua_type(L, -1) == LUA_TNUMBER) { options.stdio[i].flags = UV_INHERIT_FD; options.stdio[i].data.fd = lua_tointeger(L, -1); } // userdata is assumed to be a uv_stream_t instance else if (lua_type(L, -1) == LUA_TUSERDATA) { uv_os_fd_t fd; uv_stream_t* stream = luv_check_stream(L, -1); int err = uv_fileno((uv_handle_t*)stream, &fd); if (err == UV_EINVAL || err == UV_EBADF) { // stdin (fd 0) is read-only, stdout and stderr (fds 1 & 2) are // write-only, and all fds > 2 are read-write int flags = UV_CREATE_PIPE; if (i == 0 || i > 2) flags |= UV_READABLE_PIPE; if (i != 0) flags |= UV_WRITABLE_PIPE; options.stdio[i].flags = (uv_stdio_flags)flags; } else { options.stdio[i].flags = UV_INHERIT_STREAM; } options.stdio[i].data.stream = stream; } else if (lua_type(L, -1) == LUA_TNIL) { options.stdio[i].flags = UV_IGNORE; } else { luv_clean_options(&options); return luaL_argerror(L, 2, "stdio table entries must be nil, uv_stream_t, or integer"); } lua_pop(L, 1); } } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "stdio option must be table"); } lua_pop(L, 1); // Get the env lua_getfield(L, 2, "env"); if (lua_type(L, -1) == LUA_TTABLE) { len = lua_rawlen(L, -1); options.env = (char**)malloc((len + 1) * sizeof(*options.env)); if (!options.env) { luv_clean_options(&options); return luaL_error(L, "Problem allocating env"); } for (i = 0; i < len; ++i) { lua_rawgeti(L, -1, i + 1); options.env[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } options.env[len] = NULL; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "env option must be table"); } lua_pop(L, 1); // Get the cwd lua_getfield(L, 2, "cwd"); if (lua_type(L, -1) == LUA_TSTRING) { options.cwd = (char*)lua_tostring(L, -1); } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "cwd option must be string"); } lua_pop(L, 1); // Check for uid lua_getfield(L, 2, "uid"); if (lua_type(L, -1) == LUA_TNUMBER) { options.uid = lua_tointeger(L, -1); options.flags |= UV_PROCESS_SETUID; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "uid option must be number"); } lua_pop(L, 1); // Check for gid lua_getfield(L, 2, "gid"); if (lua_type(L, -1) == LUA_TNUMBER) { options.gid = lua_tointeger(L, -1); options.flags |= UV_PROCESS_SETGID; } else if (lua_type(L, -1) != LUA_TNIL) { luv_clean_options(&options); return luaL_argerror(L, 2, "gid option must be number"); } lua_pop(L, 1); // Check for the boolean flags lua_getfield(L, 2, "verbatim"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; } lua_pop(L, 1); lua_getfield(L, 2, "detached"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_DETACHED; } lua_pop(L, 1); lua_getfield(L, 2, "hide"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_WINDOWS_HIDE; } lua_pop(L, 1); #if LUV_UV_VERSION_GEQ(1, 24, 0) lua_getfield(L, 2, "hide_console"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_WINDOWS_HIDE_CONSOLE; } lua_pop(L, 1); lua_getfield(L, 2, "hide_gui"); if (lua_toboolean(L, -1)) { options.flags |= UV_PROCESS_WINDOWS_HIDE_GUI; } lua_pop(L, 1); #endif // this will fill the 3rd argument with nil if it doesn't exist so that // the uv_process_t userdata doesn't get treated as the 3rd argument lua_settop(L, 3); handle = (uv_process_t*)luv_newuserdata(L, sizeof(*handle)); handle->type = UV_PROCESS; handle->data = luv_setup_handle(L, ctx); if (!lua_isnoneornil(L, 3)) { luv_check_callback(L, (luv_handle_t*)handle->data, LUV_EXIT, 3); } ret = uv_spawn(ctx->loop, handle, &options); luv_clean_options(&options); if (ret < 0) { /* The async callback is required here because luajit GC may reclaim the * luv handle before libuv is done closing it down. */ uv_close((uv_handle_t*)handle, luv_spawn_close_cb); return luv_error(L, ret); } lua_pushinteger(L, handle->pid); return 2; } static int luv_parse_signal(lua_State* L, int slot) { if (lua_isnumber(L, slot)) { return lua_tonumber(L, slot); } if (lua_isstring(L, slot)) { return luv_sig_string_to_num(lua_tostring(L, slot)); } return SIGTERM; } static int luv_process_kill(lua_State* L) { uv_process_t* handle = luv_check_process(L, 1); int signum = luv_parse_signal(L, 2); int ret = uv_process_kill(handle, signum); return luv_result(L, ret); } static int luv_kill(lua_State* L) { int pid = luaL_checkinteger(L, 1); int signum = luv_parse_signal(L, 2); int ret = uv_kill(pid, signum); return luv_result(L, ret); } luv-1.36.0-0/src/req.c000066400000000000000000000031531364617304100142750ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_req_t* luv_check_req(lua_State* L, int index) { uv_req_t* req = (uv_req_t*)luaL_checkudata(L, index, "uv_req"); luaL_argcheck(L, req->data, index, "Expected uv_req_t"); return req; } static int luv_req_tostring(lua_State* L) { uv_req_t* req = (uv_req_t*)luaL_checkudata(L, 1, "uv_req"); switch (req->type) { #define XX(uc, lc) case UV_##uc: lua_pushfstring(L, "uv_"#lc"_t: %p", req); break; UV_REQ_TYPE_MAP(XX) #undef XX default: lua_pushfstring(L, "uv_req_t: %p", req); break; } return 1; } static void luv_req_init(lua_State* L) { luaL_newmetatable (L, "uv_req"); lua_pushcfunction(L, luv_req_tostring); lua_setfield(L, -2, "__tostring"); lua_pop(L, 1); } // Metamethod to allow storing anything in the userdata's environment static int luv_cancel(lua_State* L) { uv_req_t* req = (uv_req_t*)luv_check_req(L, 1); int ret = uv_cancel(req); // Cleanup occurs when callbacks are ran with UV_ECANCELED status. return luv_result(L, ret); } luv-1.36.0-0/src/schema.c000066400000000000000000000011741364617304100147470ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ luv-1.36.0-0/src/signal.c000066400000000000000000000055061364617304100147670ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_signal_t* luv_check_signal(lua_State* L, int index) { uv_signal_t* handle = (uv_signal_t*)luv_checkudata(L, index, "uv_signal"); luaL_argcheck(L, handle->type == UV_SIGNAL && handle->data, index, "Expected uv_signal_t"); return handle; } static int luv_new_signal(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_signal_t* handle = (uv_signal_t*)luv_newuserdata(L, sizeof(*handle)); int ret = uv_signal_init(ctx->loop, handle); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static void luv_signal_cb(uv_signal_t* handle, int signum) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; lua_pushstring(L, luv_sig_num_to_string(signum)); luv_call_callback(L, data, LUV_SIGNAL, 1); } static int luv_signal_start(lua_State* L) { uv_signal_t* handle = luv_check_signal(L, 1); int signum, ret; if (lua_isnumber(L, 2)) { signum = lua_tointeger(L, 2); } else if (lua_isstring(L, 2)) { signum = luv_sig_string_to_num(luaL_checkstring(L, 2)); luaL_argcheck(L, signum, 2, "Invalid Signal name"); } else { return luaL_argerror(L, 2, "Missing Signal name"); } if (!lua_isnoneornil(L, 3)) { luv_check_callback(L, (luv_handle_t*)handle->data, LUV_SIGNAL, 3); } ret = uv_signal_start(handle, luv_signal_cb, signum); return luv_result(L, ret); } #if LUV_UV_VERSION_GEQ(1, 12, 0) static int luv_signal_start_oneshot(lua_State* L) { uv_signal_t* handle = luv_check_signal(L, 1); int signum, ret; if (lua_isnumber(L, 2)) { signum = lua_tointeger(L, 2); } else if (lua_isstring(L, 2)) { signum = luv_sig_string_to_num(luaL_checkstring(L, 2)); luaL_argcheck(L, signum, 2, "Invalid Signal name"); } else { return luaL_argerror(L, 2, "Missing Signal name"); } if (!lua_isnoneornil(L, 3)) { luv_check_callback(L, (luv_handle_t*)handle->data, LUV_SIGNAL, 3); } ret = uv_signal_start_oneshot(handle, luv_signal_cb, signum); return luv_result(L, ret); } #endif static int luv_signal_stop(lua_State* L) { uv_signal_t* handle = luv_check_signal(L, 1); int ret = uv_signal_stop(handle); return luv_result(L, ret); } luv-1.36.0-0/src/stream.c000066400000000000000000000146401364617304100150040ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_stream_t* luv_check_stream(lua_State* L, int index) { int isStream; void *udata; uv_stream_t* handle; if (!(udata = lua_touserdata(L, index))) { goto fail; } if (!(handle = *(uv_stream_t**) udata)) { goto fail; } if (!handle->data) { goto fail; } lua_getfield(L, LUA_REGISTRYINDEX, "uv_stream"); lua_getmetatable(L, index < 0 ? index - 1 : index); lua_rawget(L, -2); isStream = lua_toboolean(L, -1); lua_pop(L, 2); if (isStream) { return handle; } fail: luaL_argerror(L, index, "Expected uv_stream userdata"); return NULL; } static void luv_shutdown_cb(uv_shutdown_t* req, int status) { luv_req_t* data = (luv_req_t*)req->data; lua_State* L = data->ctx->L; luv_status(L, status); luv_fulfill_req(L, (luv_req_t*)req->data, 1); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; } static int luv_shutdown(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_stream_t* handle = luv_check_stream(L, 1); int ref = luv_check_continuation(L, 2); uv_shutdown_t* req = (uv_shutdown_t*)lua_newuserdata(L, sizeof(*req)); int ret; req->data = luv_setup_req(L, ctx, ref); ret = uv_shutdown(req, handle, luv_shutdown_cb); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } return 1; } static void luv_connection_cb(uv_stream_t* handle, int status) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; luv_status(L, status); luv_call_callback(L, (luv_handle_t*)handle->data, LUV_CONNECTION, 1); } static int luv_listen(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); int backlog = luaL_checkinteger(L, 2); int ret; luv_check_callback(L, (luv_handle_t*)handle->data, LUV_CONNECTION, 3); ret = uv_listen(handle, backlog, luv_connection_cb); return luv_result(L, ret); } static int luv_accept(lua_State* L) { uv_stream_t* server = luv_check_stream(L, 1); uv_stream_t* client = luv_check_stream(L, 2); int ret = uv_accept(server, client); return luv_result(L, ret); } static void luv_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { (void)handle; buf->base = (char*)malloc(suggested_size); assert(buf->base); buf->len = suggested_size; } static void luv_read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; int nargs; if (nread > 0) { lua_pushnil(L); lua_pushlstring(L, buf->base, nread); nargs = 2; } free(buf->base); if (nread == 0) return; if (nread == UV_EOF) { nargs = 0; } else if (nread < 0) { luv_status(L, nread); nargs = 1; } luv_call_callback(L, (luv_handle_t*)handle->data, LUV_READ, nargs); } static int luv_read_start(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); int ret; luv_check_callback(L, (luv_handle_t*)handle->data, LUV_READ, 2); ret = uv_read_start(handle, luv_alloc_cb, luv_read_cb); return luv_result(L, ret); } static int luv_read_stop(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); int ret = uv_read_stop(handle); return luv_result(L, ret); } static void luv_write_cb(uv_write_t* req, int status) { luv_req_t* data = (luv_req_t*)req->data; lua_State* L = data->ctx->L; luv_status(L, status); luv_fulfill_req(L, (luv_req_t*)req->data, 1); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; } static int luv_write(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_stream_t* handle = luv_check_stream(L, 1); uv_write_t* req; int ret, ref; ref = luv_check_continuation(L, 3); req = (uv_write_t *)lua_newuserdata(L, sizeof(*req)); req->data = (luv_req_t*)luv_setup_req(L, ctx, ref); size_t count; uv_buf_t* bufs = luv_check_bufs(L, 2, &count, (luv_req_t*)req->data); ret = uv_write(req, handle, bufs, count, luv_write_cb); free(bufs); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } return 1; } static int luv_write2(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_stream_t* handle = luv_check_stream(L, 1); uv_write_t* req; int ret, ref; uv_stream_t* send_handle; send_handle = luv_check_stream(L, 3); ref = luv_check_continuation(L, 4); req = (uv_write_t *)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ctx, ref); size_t count; uv_buf_t* bufs = luv_check_bufs(L, 2, &count, (luv_req_t*)req->data); ret = uv_write2(req, handle, bufs, count, send_handle, luv_write_cb); free(bufs); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } return 1; } static int luv_try_write(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); int err_or_num_bytes; size_t count; uv_buf_t* bufs = luv_check_bufs_noref(L, 2, &count); err_or_num_bytes = uv_try_write(handle, bufs, count); free(bufs); if (err_or_num_bytes < 0) return luv_error(L, err_or_num_bytes); lua_pushinteger(L, err_or_num_bytes); return 1; } static int luv_is_readable(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); lua_pushboolean(L, uv_is_readable(handle)); return 1; } static int luv_is_writable(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); lua_pushboolean(L, uv_is_writable(handle)); return 1; } static int luv_stream_set_blocking(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); int blocking, ret; luaL_checktype(L, 2, LUA_TBOOLEAN); blocking = lua_toboolean(L, 2); ret = uv_stream_set_blocking(handle, blocking); return luv_result(L, ret); } #if LUV_UV_VERSION_GEQ(1, 19, 0) static int luv_stream_get_write_queue_size(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); lua_pushinteger(L, uv_stream_get_write_queue_size(handle)); return 1; } #endif luv-1.36.0-0/src/tcp.c000066400000000000000000000154261364617304100143020ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_tcp_t* luv_check_tcp(lua_State* L, int index) { uv_tcp_t* handle = (uv_tcp_t*)luv_checkudata(L, index, "uv_tcp"); luaL_argcheck(L, handle->type == UV_TCP && handle->data, index, "Expected uv_tcp_t"); return handle; } static int luv_new_tcp(lua_State* L) { uv_tcp_t* handle; int ret; luv_ctx_t* ctx = luv_context(L); lua_settop(L, 1); handle = (uv_tcp_t*)luv_newuserdata(L, sizeof(*handle)); #if LUV_UV_VERSION_GEQ(1, 7, 0) if (lua_isnoneornil(L, 1)) { ret = uv_tcp_init(ctx->loop, handle); } else { unsigned int flags = AF_UNSPEC; if (lua_isnumber(L, 1)) { flags = lua_tointeger(L, 1); } else if (lua_isstring(L, 1)) { const char* family = lua_tostring(L, 1); flags = luv_af_string_to_num(family); if (!flags) { luaL_argerror(L, 1, lua_pushfstring(L, "invalid or unknown address family: '%s'", family)); } } else { luaL_argerror(L, 1, "expected string or integer"); } ret = uv_tcp_init_ex(ctx->loop, handle, flags); } #else ret = uv_tcp_init(ctx->loop, handle); #endif if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static int luv_tcp_open(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); uv_os_sock_t sock = luaL_checkinteger(L, 2); int ret = uv_tcp_open(handle, sock); return luv_result(L, ret); } static int luv_tcp_nodelay(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); int ret, enable; luaL_checktype(L, 2, LUA_TBOOLEAN); enable = lua_toboolean(L, 2); ret = uv_tcp_nodelay(handle, enable); return luv_result(L, ret); } static int luv_tcp_keepalive(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); int ret, enable; unsigned int delay = 0; luaL_checktype(L, 2, LUA_TBOOLEAN); enable = lua_toboolean(L, 2); if (enable) { delay = luaL_checkinteger(L, 3); } ret = uv_tcp_keepalive(handle, enable, delay); return luv_result(L, ret); } static int luv_tcp_simultaneous_accepts(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); int ret, enable; luaL_checktype(L, 2, LUA_TBOOLEAN); enable = lua_toboolean(L, 2); ret = uv_tcp_simultaneous_accepts(handle, enable); return luv_result(L, ret); } static int luv_tcp_bind(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); const char* host = luaL_checkstring(L, 2); int port = luaL_checkinteger(L, 3); unsigned int flags = 0; struct sockaddr_storage addr; int ret; if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); } if (lua_type(L, 4) == LUA_TTABLE) { lua_getfield(L, 4, "ipv6only"); if (lua_toboolean(L, -1)) flags |= UV_TCP_IPV6ONLY; lua_pop(L, 1); } ret = uv_tcp_bind(handle, (struct sockaddr*)&addr, flags); return luv_result(L, ret); } static void parse_sockaddr(lua_State* L, struct sockaddr_storage* address) { char ip[INET6_ADDRSTRLEN]; int port = 0; lua_newtable(L); if (address->ss_family == AF_INET) { struct sockaddr_in* addrin = (struct sockaddr_in*)address; uv_inet_ntop(AF_INET, &(addrin->sin_addr), ip, INET6_ADDRSTRLEN); port = ntohs(addrin->sin_port); } else if (address->ss_family == AF_INET6) { struct sockaddr_in6* addrin6 = (struct sockaddr_in6*)address; uv_inet_ntop(AF_INET6, &(addrin6->sin6_addr), ip, INET6_ADDRSTRLEN); port = ntohs(addrin6->sin6_port); } lua_pushstring(L, luv_af_num_to_string(address->ss_family)); lua_setfield(L, -2, "family"); lua_pushinteger(L, port); lua_setfield(L, -2, "port"); lua_pushstring(L, ip); lua_setfield(L, -2, "ip"); } static int luv_tcp_getsockname(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); struct sockaddr_storage address; int addrlen = sizeof(address); int ret = uv_tcp_getsockname(handle, (struct sockaddr*)&address, &addrlen); if (ret < 0) return luv_error(L, ret); parse_sockaddr(L, &address); return 1; } static int luv_tcp_getpeername(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); struct sockaddr_storage address; int addrlen = sizeof(address); int ret = uv_tcp_getpeername(handle, (struct sockaddr*)&address, &addrlen); if (ret < 0) return luv_error(L, ret); parse_sockaddr(L, &address); return 1; } static void luv_connect_cb(uv_connect_t* req, int status) { luv_req_t* data = (luv_req_t*)req->data; lua_State* L = data->ctx->L; luv_status(L, status); luv_fulfill_req(L, (luv_req_t*)req->data, 1); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; } // deprecated by luv_stream_get_write_queue_size static int luv_write_queue_size(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); lua_pushinteger(L, handle->write_queue_size); return 1; } static int luv_tcp_connect(lua_State* L) { uv_tcp_t* handle = luv_check_tcp(L, 1); const char* host = luaL_checkstring(L, 2); int port = luaL_checkinteger(L, 3); struct sockaddr_storage addr; uv_connect_t* req; int ret, ref; luv_handle_t* lhandle = handle->data; if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); } ref = luv_check_continuation(L, 4); req = (uv_connect_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, lhandle->ctx, ref); ret = uv_tcp_connect(req, handle, (struct sockaddr*)&addr, luv_connect_cb); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } return 1; } #if LUV_UV_VERSION_GEQ(1, 32, 0) static void luv_close_reset_cb(uv_handle_t* handle) { lua_State* L; luv_handle_t* data = (luv_handle_t*)handle->data; if (!data) return; L = data->ctx->L; luv_call_callback(L, data, LUV_RESET, 0); luv_unref_handle(L, data); } static int luv_tcp_close_reset(lua_State* L) { int ret; uv_tcp_t* handle = luv_check_tcp(L, 1); if (!lua_isnoneornil(L, 2)) { luv_check_callback(L, (luv_handle_t*)handle->data, LUV_RESET, 2); } ret = uv_tcp_close_reset(handle, luv_close_reset_cb); return luv_result(L, ret); } #endif luv-1.36.0-0/src/thread.c000066400000000000000000000242111364617304100147530ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" typedef struct { uv_thread_t handle; char* code; int len; int argc; luv_thread_arg_t args; } luv_thread_t; static lua_State* luv_thread_acquire_vm() { lua_State* L = luaL_newstate(); // Add in the lua standard libraries luaL_openlibs(L); // Get package.loaded, so we can store uv in it. lua_getglobal(L, "package"); lua_getfield(L, -1, "loaded"); lua_remove(L, -2); // Remove package // Store uv module definition at loaded.uv luaopen_luv(L); lua_setfield(L, -2, "luv"); lua_pop(L, 1); return L; } static void luv_thread_release_vm(lua_State* L) { lua_close(L); } static const char* luv_getmtname(lua_State *L, int idx) { const char* name; lua_getmetatable(L, idx); lua_pushstring(L, "__name"); lua_rawget(L, -2); name = lua_tostring(L, -1); lua_pop(L, 2); return name; } static int luv_thread_arg_set(lua_State* L, luv_thread_arg_t* args, int idx, int top, int flags) { int i; int side = LUVF_THREAD_SIDE(flags); int async = LUVF_THREAD_ASYNC(flags); idx = idx > 0 ? idx : 1; i = idx; args->flags = flags; while (i <= top && i <= LUV_THREAD_MAXNUM_ARG + idx) { luv_val_t *arg = args->argv + i - idx; arg->type = lua_type(L, i); arg->ref[0] = arg->ref[1] = LUA_NOREF; switch (arg->type) { case LUA_TNIL: break; case LUA_TBOOLEAN: arg->val.boolean = lua_toboolean(L, i); break; case LUA_TNUMBER: arg->val.num = lua_tonumber(L, i); break; case LUA_TSTRING: if (async) { const char* p = lua_tolstring(L, i, &arg->val.str.len); arg->val.str.base = malloc(arg->val.str.len); memcpy((void*)arg->val.str.base, p, arg->val.str.len); } else { arg->val.str.base = lua_tolstring(L, i, &arg->val.str.len); lua_pushvalue(L, i); arg->ref[side] = luaL_ref(L, LUA_REGISTRYINDEX); } break; case LUA_TUSERDATA: arg->val.udata.data = lua_topointer(L, i); arg->val.udata.size = lua_rawlen(L, i); arg->val.udata.metaname = luv_getmtname(L, i); if (arg->val.udata.size) { lua_pushvalue(L, i); arg->ref[side] = luaL_ref(L, LUA_REGISTRYINDEX); } break; default: fprintf(stderr, "Error: thread arg not support type '%s' at %d", lua_typename(L, arg->type), i); arg->val.str.base = NULL; arg->val.str.len = 0; break; } i++; } args->argc = i - idx; return args->argc; } static void luv_thread_arg_clear(lua_State* L, luv_thread_arg_t* args, int flags) { int i; int side = LUVF_THREAD_SIDE(flags); int set = LUVF_THREAD_SIDE(args->flags); int async = LUVF_THREAD_ASYNC(args->flags); if (args->argc == 0) return; for (i = 0; i < args->argc; i++) { luv_val_t* arg = args->argv + i; switch (arg->type) { case LUA_TSTRING: if (arg->ref[side] != LUA_NOREF) { luaL_unref(L, LUA_REGISTRYINDEX, arg->ref[side]); arg->ref[side] = LUA_NOREF; } else { if(async && set!=side) { free((void*)arg->val.str.base); arg->val.str.base = NULL; arg->val.str.len = 0; } } break; case LUA_TUSERDATA: if (arg->ref[side]!=LUA_NOREF) { if (side != set) { // avoid custom gc lua_rawgeti(L, LUA_REGISTRYINDEX, arg->ref[side]); lua_pushnil(L); lua_setmetatable(L, -2); lua_pop(L, -1); } luaL_unref(L, LUA_REGISTRYINDEX, arg->ref[side]); arg->ref[side] = LUA_NOREF; } break; default: break; } } } // called only in thread static int luv_thread_arg_push(lua_State* L, luv_thread_arg_t* args, int flags) { int i = 0; int side = LUVF_THREAD_SIDE(flags); while (i < args->argc) { luv_val_t* arg = args->argv + i; switch (arg->type) { case LUA_TNIL: lua_pushnil(L); break; case LUA_TBOOLEAN: lua_pushboolean(L, arg->val.boolean); break; case LUA_TNUMBER: lua_pushnumber(L, arg->val.num); break; case LUA_TSTRING: lua_pushlstring(L, arg->val.str.base, arg->val.str.len); break; case LUA_TUSERDATA: if (arg->val.udata.size) { char *p = lua_newuserdata(L, arg->val.udata.size); memcpy(p, arg->val.udata.data, arg->val.udata.size); if (arg->val.udata.metaname) { luaL_getmetatable(L, arg->val.udata.metaname); lua_setmetatable(L, -2); } lua_pushvalue(L, -1); arg->ref[side] = luaL_ref(L, LUA_REGISTRYINDEX); }else{ lua_pushlightuserdata(L, (void*)arg->val.udata.data); } break; default: fprintf(stderr, "Error: thread arg not support type %s at %d", lua_typename(L, arg->type), i + 1); } i++; }; return i; } int thread_dump(lua_State* L, const void* p, size_t sz, void* B) { (void)L; luaL_addlstring((luaL_Buffer*) B, (const char*) p, sz); return 0; } static const char* luv_thread_dumped(lua_State* L, int idx, size_t* l) { if (lua_isstring(L, idx)) { return lua_tolstring(L, idx, l); } else { const char* buff = NULL; int top = lua_gettop(L); luaL_Buffer b; int test_lua_dump; luaL_checktype(L, idx, LUA_TFUNCTION); lua_pushvalue(L, idx); luaL_buffinit(L, &b); test_lua_dump = (lua_dump(L, thread_dump, &b, 1) == 0); if (test_lua_dump) { luaL_pushresult(&b); buff = lua_tolstring(L, -1, l); } else luaL_error(L, "Error: unable to dump given function"); lua_settop(L, top); return buff; } } static luv_thread_t* luv_check_thread(lua_State* L, int index) { luv_thread_t* thread = (luv_thread_t*)luaL_checkudata(L, index, "uv_thread"); return thread; } static int luv_thread_gc(lua_State* L) { luv_thread_t* tid = luv_check_thread(L, 1); free(tid->code); tid->code = NULL; tid->len = 0; luv_thread_arg_clear(L, &tid->args, LUVF_THREAD_SIDE_MAIN); return 0; } static int luv_thread_tostring(lua_State* L) { luv_thread_t* thd = luv_check_thread(L, 1); lua_pushfstring(L, "uv_thread_t: %p", (void*)thd->handle); return 1; } static void luv_thread_cb(void* varg) { //acquire vm and get top luv_thread_t* thd = (luv_thread_t*)varg; lua_State* L = acquire_vm_cb(); //push lua function, thread entry if (luaL_loadbuffer(L, thd->code, thd->len, "=thread") == 0) { //push parameter for real thread function int i = luv_thread_arg_push(L, &thd->args, LUVF_THREAD_SIDE_CHILD); luv_cfpcall(L, i, 0, 0); luv_thread_arg_clear(L, &thd->args, LUVF_THREAD_SIDE_CHILD); } else { fprintf(stderr, "Uncaught Error in thread: %s\n", lua_tostring(L, -1)); //pop errmsg lua_pop(L, 1); } release_vm_cb(L); } static int luv_new_thread(lua_State* L) { int ret; size_t len; const char* buff; luv_thread_t* thread; int cbidx = 1; #if LUV_UV_VERSION_GEQ(1, 26, 0) uv_thread_options_t options; options.flags = UV_THREAD_NO_FLAGS; if (lua_type(L, 1) == LUA_TTABLE) { cbidx++; lua_getfield(L, 1, "stack_size"); if (!lua_isnil(L, -1)) { options.flags |= UV_THREAD_HAS_STACK_SIZE; if (lua_isnumber(L, -1)) { options.stack_size = lua_tointeger(L, -1); } else { return luaL_argerror(L, 1, "stack_size option must be a number if set"); } } lua_pop(L, 1); } #endif buff = luv_thread_dumped(L, cbidx, &len); thread = (luv_thread_t*)lua_newuserdata(L, sizeof(*thread)); memset(thread, 0, sizeof(*thread)); luaL_getmetatable(L, "uv_thread"); lua_setmetatable(L, -2); //clear in luv_thread_gc or in child threads thread->argc = luv_thread_arg_set(L, &thread->args, cbidx+1, lua_gettop(L) - 1, LUVF_THREAD_SIDE_MAIN); thread->len = len; thread->code = (char*)malloc(thread->len); memcpy(thread->code, buff, len); #if LUV_UV_VERSION_GEQ(1, 26, 0) ret = uv_thread_create_ex(&thread->handle, &options, luv_thread_cb, thread); #else ret = uv_thread_create(&thread->handle, luv_thread_cb, thread); #endif if (ret < 0) return luv_error(L, ret); return 1; } static int luv_thread_join(lua_State* L) { luv_thread_t* tid = luv_check_thread(L, 1); int ret = uv_thread_join(&tid->handle); if (ret < 0) return luv_error(L, ret); lua_pushboolean(L, 1); return 1; } static int luv_thread_self(lua_State* L) { luv_thread_t* thread; uv_thread_t t = uv_thread_self(); thread = (luv_thread_t*)lua_newuserdata(L, sizeof(*thread)); memset(thread, 0, sizeof(*thread)); memcpy(&thread->handle, &t, sizeof(t)); luaL_getmetatable(L, "uv_thread"); lua_setmetatable(L, -2); return 1; } static int luv_thread_equal(lua_State* L) { luv_thread_t* t1 = luv_check_thread(L, 1); luv_thread_t* t2 = luv_check_thread(L, 2); int ret = uv_thread_equal(&t1->handle, &t2->handle); lua_pushboolean(L, ret); return 1; } static const luaL_Reg luv_thread_methods[] = { {"equal", luv_thread_equal}, {"join", luv_thread_join}, {NULL, NULL} }; static void luv_thread_init(lua_State* L) { luaL_newmetatable(L, "uv_thread"); lua_pushcfunction(L, luv_thread_tostring); lua_setfield(L, -2, "__tostring"); lua_pushcfunction(L, luv_thread_equal); lua_setfield(L, -2, "__eq"); lua_pushcfunction(L, luv_thread_gc); lua_setfield(L, -2, "__gc"); lua_newtable(L); luaL_setfuncs(L, luv_thread_methods, 0); lua_setfield(L, -2, "__index"); lua_pop(L, 1); if (acquire_vm_cb == NULL) acquire_vm_cb = luv_thread_acquire_vm; if (release_vm_cb == NULL) release_vm_cb = luv_thread_release_vm; } LUALIB_API void luv_set_thread_cb(luv_acquire_vm acquire, luv_release_vm release) { acquire_vm_cb = acquire; release_vm_cb = release; } luv-1.36.0-0/src/timer.c000066400000000000000000000046571364617304100146400ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_timer_t* luv_check_timer(lua_State* L, int index) { uv_timer_t* handle = (uv_timer_t*) luv_checkudata(L, index, "uv_timer"); luaL_argcheck(L, handle->type == UV_TIMER && handle->data, index, "Expected uv_timer_t"); return handle; } static int luv_new_timer(lua_State* L) { luv_ctx_t* ctx = luv_context(L); uv_timer_t* handle = (uv_timer_t*) luv_newuserdata(L, sizeof(*handle)); int ret = uv_timer_init(ctx->loop, handle); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static void luv_timer_cb(uv_timer_t* handle) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; luv_call_callback(L, data, LUV_TIMEOUT, 0); } static int luv_timer_start(lua_State* L) { uv_timer_t* handle = luv_check_timer(L, 1); uint64_t timeout; uint64_t repeat; int ret; timeout = luaL_checkinteger(L, 2); repeat = luaL_checkinteger(L, 3); luv_check_callback(L, (luv_handle_t*)handle->data, LUV_TIMEOUT, 4); ret = uv_timer_start(handle, luv_timer_cb, timeout, repeat); return luv_result(L, ret); } static int luv_timer_stop(lua_State* L) { uv_timer_t* handle = luv_check_timer(L, 1); int ret = uv_timer_stop(handle); return luv_result(L, ret); } static int luv_timer_again(lua_State* L) { uv_timer_t* handle = luv_check_timer(L, 1); int ret = uv_timer_again(handle); return luv_result(L, ret); } static int luv_timer_set_repeat(lua_State* L) { uv_timer_t* handle = luv_check_timer(L, 1); uint64_t repeat = luaL_checkinteger(L, 2); uv_timer_set_repeat(handle, repeat); return 0; } static int luv_timer_get_repeat(lua_State* L) { uv_timer_t* handle = luv_check_timer(L, 1); uint64_t repeat = uv_timer_get_repeat(handle); lua_pushinteger(L, repeat); return 1; } luv-1.36.0-0/src/tty.c000066400000000000000000000052751364617304100143350ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_tty_t* luv_check_tty(lua_State* L, int index) { uv_tty_t* handle = (uv_tty_t*)luv_checkudata(L, index, "uv_tty"); luaL_argcheck(L, handle->type == UV_TTY && handle->data, index, "Expected uv_tty_t"); return handle; } static int luv_new_tty(lua_State* L) { int readable, ret; uv_tty_t* handle; luv_ctx_t* ctx = luv_context(L); uv_file fd = luaL_checkinteger(L, 1); luaL_checktype(L, 2, LUA_TBOOLEAN); readable = lua_toboolean(L, 2); handle = (uv_tty_t*)luv_newuserdata(L, sizeof(*handle)); ret = uv_tty_init(ctx->loop, handle, fd, readable); if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static int luv_tty_set_mode(lua_State* L) { uv_tty_t* handle = luv_check_tty(L, 1); int mode = luaL_checkinteger(L, 2); int ret = uv_tty_set_mode(handle, mode); return luv_result(L, ret); } static int luv_tty_reset_mode(lua_State* L) { int ret = uv_tty_reset_mode(); return luv_result(L, ret); } static int luv_tty_get_winsize(lua_State* L) { uv_tty_t* handle = luv_check_tty(L, 1); int width, height; int ret = uv_tty_get_winsize(handle, &width, &height); if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, width); lua_pushinteger(L, height); return 2; } #if LUV_UV_VERSION_GEQ(1, 33, 0) int luv_tty_set_vterm_state(lua_State* L) { uv_tty_vtermstate_t state[] = {UV_TTY_SUPPORTED, UV_TTY_UNSUPPORTED}; const char* option[] = {"supported", "unsupported", NULL}; int idx = luaL_checkoption (L, 1, NULL, option); uv_tty_set_vterm_state(state[idx]); return 0; } int luv_tty_get_vterm_state(lua_State* L) { uv_tty_vtermstate_t state; int ret = uv_tty_get_vterm_state(&state); if (ret < 0) return luv_error(L, ret); switch (state) { case UV_TTY_SUPPORTED: lua_pushliteral(L, "supported"); ret = 1; break; case UV_TTY_UNSUPPORTED: lua_pushliteral(L, "unsupported"); ret = 1; break; default: ret = luaL_error(L, "unexpected uv_tty_vtermstate: %d", state); } return ret; } #endif luv-1.36.0-0/src/udp.c000066400000000000000000000253001364617304100142740ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" static uv_udp_t* luv_check_udp(lua_State* L, int index) { uv_udp_t* handle = (uv_udp_t*)luv_checkudata(L, index, "uv_udp"); luaL_argcheck(L, handle->type == UV_UDP && handle->data, index, "Expected uv_udp_t"); return handle; } static int luv_new_udp(lua_State* L) { luv_ctx_t* ctx = luv_context(L); lua_settop(L, 1); uv_udp_t* handle = (uv_udp_t*)luv_newuserdata(L, sizeof(*handle)); int ret; #if LUV_UV_VERSION_GEQ(1, 7, 0) if (lua_isnoneornil(L, 1)) { ret = uv_udp_init(ctx->loop, handle); } else { unsigned int flags = AF_UNSPEC; if (lua_isnumber(L, 1)) { flags = lua_tointeger(L, 1); } else if (lua_isstring(L, 1)) { const char* family = lua_tostring(L, 1); flags = luv_af_string_to_num(family); if (!flags) { luaL_argerror(L, 1, lua_pushfstring(L, "invalid or unknown address family: '%s'", family)); } } else { luaL_argerror(L, 1, "expected string or integer"); } ret = uv_udp_init_ex(ctx->loop, handle, flags); } #else ret = uv_udp_init(ctx->loop, handle); #endif if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } handle->data = luv_setup_handle(L, ctx); return 1; } static int luv_udp_get_send_queue_size(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); lua_pushinteger(L, handle->send_queue_size); return 1; } static int luv_udp_get_send_queue_count(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); lua_pushinteger(L, handle->send_queue_count); return 1; } static int luv_udp_open(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); uv_os_sock_t sock = luaL_checkinteger(L, 2); int ret = uv_udp_open(handle, sock); return luv_result(L, ret); } static int luv_udp_bind(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); const char* host = luaL_checkstring(L, 2); int port = luaL_checkinteger(L, 3); unsigned int flags = 0; struct sockaddr_storage addr; int ret; if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); } if (lua_type(L, 4) == LUA_TTABLE) { luaL_checktype(L, 4, LUA_TTABLE); lua_getfield(L, 4, "reuseaddr"); if (lua_toboolean(L, -1)) flags |= UV_UDP_REUSEADDR; lua_pop(L, 1); lua_getfield(L, 4, "ipv6only"); if (lua_toboolean(L, -1)) flags |= UV_UDP_IPV6ONLY; lua_pop(L, 1); } ret = uv_udp_bind(handle, (struct sockaddr*)&addr, flags); return luv_result(L, ret); } static int luv_udp_getsockname(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); struct sockaddr_storage address; int addrlen = sizeof(address); int ret = uv_udp_getsockname(handle, (struct sockaddr*)&address, &addrlen); if (ret < 0) return luv_error(L, ret); parse_sockaddr(L, &address); return 1; } // These are the same order as uv_membership which also starts at 0 static const char *const luv_membership_opts[] = { "leave", "join", NULL }; static int luv_udp_set_membership(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); const char* multicast_addr = luaL_checkstring(L, 2); const char* interface_addr = luaL_checkstring(L, 3); uv_membership membership = (uv_membership)luaL_checkoption(L, 4, NULL, luv_membership_opts); int ret = uv_udp_set_membership(handle, multicast_addr, interface_addr, membership); return luv_result(L, ret); } static int luv_udp_set_multicast_loop(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); int on, ret; luaL_checktype(L, 2, LUA_TBOOLEAN); on = lua_toboolean(L, 2); ret = uv_udp_set_multicast_loop(handle, on); return luv_result(L, ret); } static int luv_udp_set_multicast_ttl(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); int ttl, ret; ttl = luaL_checkinteger(L, 2); ret = uv_udp_set_multicast_ttl(handle, ttl); return luv_result(L, ret); } static int luv_udp_set_multicast_interface(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); const char* interface_addr = luaL_checkstring(L, 2); int ret = uv_udp_set_multicast_interface(handle, interface_addr); return luv_result(L, ret); } static int luv_udp_set_broadcast(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); int on, ret; luaL_checktype(L, 2, LUA_TBOOLEAN); on = lua_toboolean(L, 2); ret =uv_udp_set_broadcast(handle, on); return luv_result(L, ret); } static int luv_udp_set_ttl(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); int ttl, ret; ttl = luaL_checknumber(L, 2); ret = uv_udp_set_ttl(handle, ttl); return luv_result(L, ret); } static void luv_udp_send_cb(uv_udp_send_t* req, int status) { luv_req_t* data = (luv_req_t*)req->data; lua_State* L = data->ctx->L; luv_status(L, status); luv_fulfill_req(L, (luv_req_t*)req->data, 1); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; } static struct sockaddr* luv_check_addr(lua_State *L, struct sockaddr_storage* addr, int hostidx, int portidx) { const char* host; int port; #if LUV_UV_VERSION_GEQ(1, 27, 0) int host_type, port_type; host_type = lua_type(L, hostidx); port_type = lua_type(L, portidx); if (host_type == LUA_TNIL && port_type == LUA_TNIL) { return NULL; } host = lua_tostring(L, hostidx); port = lua_tointeger(L, portidx); if (host_type == LUA_TSTRING && port_type == LUA_TNUMBER) { if (uv_ip4_addr(host, port, (struct sockaddr_in*)addr) && uv_ip6_addr(host, port, (struct sockaddr_in6*)addr)) { luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); return NULL; } return (struct sockaddr*)addr; } else { if (host_type == LUA_TNIL || port_type == LUA_TNIL) { luaL_argerror(L, host_type == LUA_TNIL ? portidx : hostidx, "Both host and port must be nil if one is nil"); } luaL_argcheck(L, host_type == LUA_TNIL || host_type == LUA_TSTRING, hostidx, "Host must be string or nil"); luaL_argcheck(L, port_type == LUA_TNIL || port_type == LUA_TNUMBER, portidx, "Port must be number or nil"); return NULL; } #else host = luaL_checkstring(L, hostidx); port = luaL_checkinteger(L, portidx); if (uv_ip4_addr(host, port, (struct sockaddr_in*)addr) && uv_ip6_addr(host, port, (struct sockaddr_in6*)addr)) { luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); return NULL; } return (struct sockaddr*)addr; #endif } static int luv_udp_send(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); uv_udp_send_t* req; int ret, ref; struct sockaddr_storage addr; struct sockaddr* addr_ptr; luv_handle_t* lhandle = handle->data; addr_ptr = luv_check_addr(L, &addr, 3, 4); ref = luv_check_continuation(L, 5); req = (uv_udp_send_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, lhandle->ctx, ref); size_t count; uv_buf_t* bufs = luv_check_bufs(L, 2, &count, (luv_req_t*)req->data); ret = uv_udp_send(req, handle, bufs, count, addr_ptr, luv_udp_send_cb); free(bufs); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } lua_pushinteger(L, ret); return 1; } static int luv_udp_try_send(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); int err_or_num_bytes; struct sockaddr_storage addr; struct sockaddr* addr_ptr; size_t count; uv_buf_t* bufs = luv_check_bufs_noref(L, 2, &count); addr_ptr = luv_check_addr(L, &addr, 3, 4); err_or_num_bytes = uv_udp_try_send(handle, bufs, count, addr_ptr); free(bufs); if (err_or_num_bytes < 0) return luv_error(L, err_or_num_bytes); lua_pushinteger(L, err_or_num_bytes); return 1; } static void luv_udp_recv_cb(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { luv_handle_t* data = (luv_handle_t*)handle->data; lua_State* L = data->ctx->L; // err if (nread < 0) { luv_status(L, nread); } else { lua_pushnil(L); } // data if (nread == 0) { if (addr) { lua_pushstring(L, ""); } else { lua_pushnil(L); } } else if (nread > 0) { lua_pushlstring(L, buf->base, nread); } else { lua_pushnil(L); } #if LUV_UV_VERSION_GEQ(1, 35, 0) // UV_UDP_MMSG_CHUNK Indicates that the message was received by recvmmsg, so the buffer provided // must not be freed by the recv_cb callback. if (buf && !(flags & UV_UDP_MMSG_CHUNK)) { free(buf->base); } #else if (buf) free(buf->base); #endif // address if (addr) { parse_sockaddr(L, (struct sockaddr_storage*)addr); } else { lua_pushnil(L); } // flags lua_newtable(L); if (flags & UV_UDP_PARTIAL) { lua_pushboolean(L, 1); lua_setfield(L, -2, "partial"); } #if LUV_UV_VERSION_GEQ(1, 35, 0) if (flags & UV_UDP_MMSG_CHUNK) { lua_pushboolean(L, 1); lua_setfield(L, -2, "mmsg_chunk"); } #endif luv_call_callback(L, (luv_handle_t*)handle->data, LUV_RECV, 4); } static int luv_udp_recv_start(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); int ret; luv_check_callback(L, (luv_handle_t*)handle->data, LUV_RECV, 2); ret = uv_udp_recv_start(handle, luv_alloc_cb, luv_udp_recv_cb); #if LUV_UV_VERSION_LEQ(1, 23, 0) #if LUV_UV_VERSION_GEQ(1, 10, 0) // in Libuv <= 1.23.0, uv_udp_recv_start will return untranslated error codes on Windows // (uv_translate_sys_error was only made public in libuv >= 1.10.0) ret = uv_translate_sys_error(ret); #endif #endif return luv_result(L, ret); } static int luv_udp_recv_stop(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); int ret = uv_udp_recv_stop(handle); return luv_result(L, ret); } #if LUV_UV_VERSION_GEQ(1, 27, 0) static int luv_udp_connect(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); struct sockaddr_storage addr; struct sockaddr* addr_ptr = luv_check_addr(L, &addr, 2, 3); int ret = uv_udp_connect(handle, addr_ptr); return luv_result(L, ret); } static int luv_udp_getpeername(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); struct sockaddr_storage address; int addrlen = sizeof(address); int ret = uv_udp_getpeername(handle, (struct sockaddr*)&address, &addrlen); if (ret < 0) return luv_error(L, ret); parse_sockaddr(L, &address); return 1; } #endif luv-1.36.0-0/src/util.c000066400000000000000000000065371364617304100144740ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" void luv_stack_dump(lua_State* L, const char* name) { int i, l; fprintf(stderr, "\nAPI STACK DUMP %p %d: %s\n", L, lua_status(L), name); for (i = 1, l = lua_gettop(L); i <= l; i++) { int type = lua_type(L, i); switch (type) { case LUA_TSTRING: fprintf(stderr, " %d %s \"%s\"\n", i, lua_typename(L, type), lua_tostring(L, i)); break; case LUA_TNUMBER: fprintf(stderr, " %d %s %ld\n", i, lua_typename(L, type), (long int) lua_tointeger(L, i)); break; case LUA_TUSERDATA: fprintf(stderr, " %d %s %p\n", i, lua_typename(L, type), lua_touserdata(L, i)); break; default: fprintf(stderr, " %d %s\n", i, lua_typename(L, type)); break; } } assert(l == lua_gettop(L)); } static int luv_error(lua_State* L, int status) { assert(status < 0); lua_pushnil(L); lua_pushfstring(L, "%s: %s", uv_err_name(status), uv_strerror(status)); lua_pushstring(L, uv_err_name(status)); return 3; } static int luv_result(lua_State* L, int status) { if (status < 0) return luv_error(L, status); lua_pushinteger(L, status); return 1; } static void luv_status(lua_State* L, int status) { if (status < 0) { lua_pushstring(L, uv_err_name(status)); } else { lua_pushnil(L); } } static int luv_is_callable(lua_State* L, int index) { if (luaL_getmetafield(L, index, "__call") != LUA_TNIL) { // getmetatable(x).__call must be a function for x() to work int callable = lua_isfunction(L, -1); lua_pop(L, 1); return callable; } return lua_isfunction(L, index); } static void luv_check_callable(lua_State* L, int index) { const char *msg; const char *typearg; /* name for the type of the actual argument */ if (luv_is_callable(L, index)) return; if (luaL_getmetafield(L, index, "__name") == LUA_TSTRING) typearg = lua_tostring(L, -1); /* use the given type name */ else if (lua_type(L, index) == LUA_TLIGHTUSERDATA) typearg = "light userdata"; /* special name for messages */ else typearg = luaL_typename(L, index); /* standard name */ msg = lua_pushfstring(L, "function or callable table expected, got %s", typearg); luaL_argerror(L, index, msg); } #if LUV_UV_VERSION_GEQ(1, 10, 0) static int luv_translate_sys_error(lua_State* L) { int status = luaL_checkinteger(L, 1); status = uv_translate_sys_error(status); if (status < 0) { luv_error(L, status); lua_remove(L, -3); return 2; } return 0; } #endif static int luv_optboolean(lua_State*L, int idx, int val) { idx = lua_absindex(L, idx); luaL_argcheck(L, lua_isboolean(L, idx) || lua_isnoneornil(L, idx), idx, "Expected boolean or nil"); if (lua_isboolean(L, idx)) val = lua_toboolean(L, idx); return val; } luv-1.36.0-0/src/util.h000066400000000000000000000017161364617304100144730ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef LUV_UTIL_H #define LUV_UTIL_H #include "luv.h" #define LUV_UV_VERSION_GEQ(major, minor, patch) \ (((major)<<16 | (minor)<<8 | (patch)) <= UV_VERSION_HEX) #define LUV_UV_VERSION_LEQ(major, minor, patch) \ (((major)<<16 | (minor)<<8 | (patch)) >= UV_VERSION_HEX) void luv_stack_dump(lua_State* L, const char* name); #endif luv-1.36.0-0/src/work.c000066400000000000000000000145021364617304100144700ustar00rootroot00000000000000/* * Copyright 2014 The Luvit Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "private.h" typedef struct { lua_State* L; /* vm in main */ char* code; /* thread entry code */ size_t len; int after_work_cb; /* ref, run in main ,call after work cb*/ int pool_ref; /* ref of lua_State cache array */ } luv_work_ctx_t; typedef struct { uv_work_t work; luv_work_ctx_t* ctx; luv_thread_arg_t args; luv_thread_arg_t rets; int ref; /* ref to luv_work_ctx_t, which create a new uv_work_t*/ } luv_work_t; static luv_work_ctx_t* luv_check_work_ctx(lua_State* L, int index) { luv_work_ctx_t* ctx = (luv_work_ctx_t*)luaL_checkudata(L, index, "luv_work_ctx"); return ctx; } static int luv_work_ctx_gc(lua_State *L) { int i, n; luv_work_ctx_t* ctx = luv_check_work_ctx(L, 1); free(ctx->code); luaL_unref(L, LUA_REGISTRYINDEX, ctx->after_work_cb); lua_rawgeti(L, LUA_REGISTRYINDEX, ctx->pool_ref); n = lua_rawlen(L, -1); for (i=1; i<=n; i++) { lua_State *S; lua_rawgeti(L, -1, i); S = *(lua_State**)lua_touserdata(L, -1); release_vm_cb(S); lua_pop(L, 1); } luaL_unref(L, LUA_REGISTRYINDEX, ctx->pool_ref); return 0; } static int luv_work_ctx_tostring(lua_State* L) { luv_work_ctx_t* ctx = luv_check_work_ctx(L, 1); lua_pushfstring(L, "luv_work_ctx_t: %p", ctx); return 1; } static void luv_work_cb(uv_work_t* req) { luv_work_t* work = (luv_work_t*)req->data; luv_work_ctx_t* ctx = work->ctx; lua_State *L = work->args.L; int top = lua_gettop(L); /* push lua function */ lua_pushlstring(L, ctx->code, ctx->len); lua_rawget(L, LUA_REGISTRYINDEX); if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_pushlstring(L, ctx->code, ctx->len); if (luaL_loadbuffer(L, ctx->code, ctx->len, "=pool") != 0) { fprintf(stderr, "Uncaught Error in work callback: %s\n", lua_tostring(L, -1)); lua_pop(L, 2); lua_pushnil(L); } else { lua_pushvalue(L, -1); lua_insert(L, lua_gettop(L) - 2); lua_rawset(L, LUA_REGISTRYINDEX); } } if (lua_isfunction(L, -1)) { int i = luv_thread_arg_push(L, &work->args, LUVF_THREAD_SIDE_CHILD); i = luv_cfpcall(L, i, LUA_MULTRET, 0); if ( i>=0 ) { //clear in main threads, luv_after_work_cb i = luv_thread_arg_set(L, &work->rets, top + 1, lua_gettop(L), LUVF_THREAD_SIDE_CHILD); lua_pop(L, i); // pop all returned value luv_thread_arg_clear(L, &work->rets, LUVF_THREAD_SIDE_CHILD); } luv_thread_arg_clear(L, &work->args, LUVF_THREAD_SIDE_CHILD); } else { fprintf(stderr, "Uncaught Error: %s can't be work entry\n", lua_typename(L, lua_type(L,-1))); lua_pop(L, 1); luv_thread_arg_clear(L, &work->args, LUVF_THREAD_SIDE_CHILD); } work->args.L = L; if (top!=lua_gettop(L)) luaL_error(L, "stack not balance in luv_work_cb, need %d but %d", top, lua_gettop(L)); } static void luv_after_work_cb(uv_work_t* req, int status) { luv_work_t* work = (luv_work_t*)req->data; luv_work_ctx_t* ctx = work->ctx; lua_State* L = ctx->L; int i; (void)status; lua_rawgeti(L, LUA_REGISTRYINDEX, ctx->after_work_cb); i = luv_thread_arg_push(L, &work->rets, LUVF_THREAD_SIDE_MAIN); luv_cfpcall(L, i, 0, 0); //cache lua_State to reuse lua_rawgeti(L, LUA_REGISTRYINDEX, ctx->pool_ref); i = lua_rawlen(L, -1); *(lua_State**)lua_newuserdata(L, sizeof(lua_State*)) = work->args.L; lua_rawseti(L, -2, i+1); lua_pop(L, 1); //ref down to ctx, up in luv_queue_work() luaL_unref(L, LUA_REGISTRYINDEX, work->ref); work->ref = LUA_NOREF; luv_thread_arg_clear(L, &work->args, LUVF_THREAD_SIDE_MAIN); luv_thread_arg_clear(L, &work->rets, LUVF_THREAD_SIDE_MAIN); free(work); } static int luv_new_work(lua_State* L) { size_t len; const char* buff; luv_work_ctx_t* ctx; buff = luv_thread_dumped(L, 1, &len); luaL_checktype(L, 2, LUA_TFUNCTION); if(!lua_isnoneornil(L, 3)) luaL_checktype(L, 3, LUA_TFUNCTION); ctx = (luv_work_ctx_t*)lua_newuserdata(L, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); ctx->len = len; ctx->code = (char*)malloc(ctx->len); memcpy(ctx->code, buff, len); lua_pushvalue(L, 2); ctx->after_work_cb = luaL_ref(L, LUA_REGISTRYINDEX); ctx->L = L; luaL_getmetatable(L, "luv_work_ctx"); lua_setmetatable(L, -2); lua_newtable(L); ctx->pool_ref = luaL_ref(L, LUA_REGISTRYINDEX); return 1; } static int luv_queue_work(lua_State* L) { int top = lua_gettop(L); luv_work_ctx_t* ctx = luv_check_work_ctx(L, 1); luv_work_t* work = (luv_work_t*)malloc(sizeof(*work)); int ret, n; //prepare lua_State for threadpool lua_rawgeti(L, LUA_REGISTRYINDEX, ctx->pool_ref); n = lua_rawlen(L, -1); if (n > 0) { int i; lua_rawgeti(L, -1, 1); work->args.L = *(lua_State **)lua_touserdata(L, -1); lua_pop(L, 1); for(i=1; iargs.L = acquire_vm_cb(); lua_pop(L, 1); luv_thread_arg_set(L, &work->args, 2, top, LUVF_THREAD_SIDE_MAIN); //clear in sub threads,luv_work_cb work->ctx = ctx; work->work.data = work; ret = uv_queue_work(luv_loop(L), &work->work, luv_work_cb, luv_after_work_cb); if (ret < 0) { free(work); return luv_error(L, ret); } //ref up to ctx lua_pushvalue(L, 1); work->ref = luaL_ref(L, LUA_REGISTRYINDEX); lua_pushboolean(L, 1); return 1; } static const luaL_Reg luv_work_ctx_methods[] = { {"queue", luv_queue_work}, {NULL, NULL} }; static void luv_work_init(lua_State* L) { luaL_newmetatable(L, "luv_work_ctx"); lua_pushcfunction(L, luv_work_ctx_tostring); lua_setfield(L, -2, "__tostring"); lua_pushcfunction(L, luv_work_ctx_gc); lua_setfield(L, -2, "__gc"); luaL_newlib(L, luv_work_ctx_methods); lua_setfield(L, -2, "__index"); lua_pop(L, 1); } luv-1.36.0-0/tests/000077500000000000000000000000001364617304100137135ustar00rootroot00000000000000luv-1.36.0-0/tests/manual-test-cluster.lua000066400000000000000000000133171364617304100203340ustar00rootroot00000000000000-- This is quite the involved test. Basically it binds -- to a tcp port, spawns n children (one per CPU core) -- who all listen on the same shared port and act as a -- load balancing cluster. -- Then N clients are spawned that connect to the cluster -- The application itself kills the worker upon connection -- All N workers should accept exactly one request and all close. return require('lib/tap')(function (test) -- This function will be run in a child process local worker_code = string.dump(function () local dump = require('lib/utils').dump local function print(...) local n = select('#', ...) local arguments = {...} for i = 1, n do arguments[i] = tostring(arguments[i]) end local text = table.concat(arguments, "\t") text = " " .. string.gsub(text, "\n", "\n ") _G.print(text) end local function p(...) local n = select('#', ...) local arguments = { ... } for i = 1, n do arguments[i] = dump(arguments[i]) end print(table.concat(arguments, "\t")) end local uv = require('luv') local answer = -1 -- The parent is going to pass us the server handle over a pipe -- This will be our local file descriptor at PIPE_FD local pipe = uv.new_pipe(true) local pipe_fd = tonumber(os.getenv("PIPE_FD")) assert(uv.pipe_open(pipe, pipe_fd)) -- Configure the server handle local server = uv.new_tcp() local done = false local function onconnection() print("NOT ACCEPTING, already done") if done then return end local client = uv.new_tcp() assert(uv.accept(server, client)) p("New TCP", client, "on", server) p{client=client} assert(uv.write(client, "BYE!\n")); assert(uv.shutdown(client, function () uv.close(client) uv.unref(server) done = true answer = 42 end)) end -- Read the server handle from the parent local function onread(err, data) p("onread", {err=err,data=data}) assert(not err, err) if uv.pipe_pending_count(pipe) > 0 then local pending_type = uv.pipe_pending_type(pipe) p("pending_type", pending_type) assert(pending_type == "tcp") assert(uv.accept(pipe, server)) assert(uv.listen(server, 0, onconnection)) p("Received server handle from parent process", server) elseif data then p("ondata", data) else p("onend", data) end end uv.read_start(pipe, onread) -- Start the event loop! uv.run() os.exit(answer) end) local client_code = string.dump(function () local dump = require('lib/utils').dump local function print(...) local n = select('#', ...) local arguments = {...} for i = 1, n do arguments[i] = tostring(arguments[i]) end local text = table.concat(arguments, "\t") text = " " .. string.gsub(text, "\n", "\n ") _G.print(text) end local function p(...) local n = select('#', ...) local arguments = { ... } for i = 1, n do arguments[i] = dump(arguments[i]) end print(table.concat(arguments, "\t")) end local uv = require('luv') local host = os.getenv("HOST") local port = tonumber(os.getenv("PORT")) local socket = uv.new_tcp() assert(uv.tcp_connect(socket, host, port, function (err) p("client connected", {err=err}) assert(not err, err) end)) -- Start the event loop! uv.run() end) test("tcp cluster", function (print, p, expect, uv) local exepath = assert(uv.exepath()) local cpu_count = # assert(uv.cpu_info()) local left = cpu_count local server = uv.new_tcp() assert(uv.tcp_bind(server, "::1", 0)) local address = uv.tcp_getsockname(server) p{server=server,address=address} print("Master process bound to TCP port " .. address.port .. " on " .. address.ip) local function spawnWorker() local pipe = uv.new_pipe(true) local input = uv.new_pipe(false) local child, pid child, pid = assert(uv.spawn(exepath, { cwd = uv.cwd(), stdio = {input,1,2,pipe}, env= {"PIPE_FD=3"} }, expect(function (status, signal) p("Worker exited", {status=status,signal=signal}) assert(status == 42, "worker should return 42") assert(signal == 0) left = left - 1 uv.close(child) uv.close(input) uv.close(pipe) if left == 0 then p("All workers are now dead") uv.close(server) end end))) p("Spawned worker", pid, "and sending handle", server) assert(uv.write(input, worker_code)) assert(uv.write2(pipe, "123", server)) assert(uv.shutdown(input)) assert(uv.shutdown(pipe)) end local function spawnClient() local input = uv.new_pipe(false) local child, pid child, pid = assert(uv.spawn(exepath, { stdio = {input,1,2}, cwd = uv.cwd(), env= { "HOST=" .. address.ip, "PORT=" .. address.port, } }, expect(function (status, signal) p("Client exited", {status=status,signal=signal}) assert(status == 0) assert(signal == 0) uv.close(child) end, left))) p("Spawned client", pid) assert(uv.write(input, client_code)) assert(uv.shutdown(input)) uv.close(input) end -- Spawn a child process for each CPU core for _ = 1, cpu_count do spawnWorker() end -- Spawn the clients after a short delay local timer = uv.new_timer() uv.timer_start(timer, 1000, 0, expect(function () for _ = 1, cpu_count do spawnClient() end uv.close(timer) end)) end) end) luv-1.36.0-0/tests/manual-test-leaks.lua000066400000000000000000000122301364617304100177430ustar00rootroot00000000000000-- this is a primitive test for leaks that has been -- superseded by running better leak checking tools -- like Valgrind and LSAN/ASAN return require('lib/tap')(function (test) local function bench(uv, p, count, fn) collectgarbage() local before local notify = count / 8 for i = 1, count do fn() if i % notify == 0 then uv.run() collectgarbage() local now = uv.resident_set_memory() if not before then before = now end p(i, now) end end uv.run() collectgarbage() local after = uv.resident_set_memory() p{ before = before, after = after, } assert(after < before * 1.5) end test("fs-write", function (print, p, expect, uv) bench(uv, p, 0xf00, function () local path = "_test_" local fd = assert(uv.fs_open(path, "w", 438)) uv.fs_write(fd, "Hello World\n", -1) uv.fs_write(fd, {"with\n", "more\n", "lines\n"}, -1) uv.fs_close(fd) uv.fs_unlink(path) end) end) test("lots-o-timers", function (print, p, expect, uv) bench(uv, p, 0x100000, function () local timer = uv.new_timer() uv.close(timer) end) end) test("lots-o-timers with canceled callbacks", function (print, p, expect, uv) bench(uv, p, 0x10000, function () local timer = uv.new_timer() uv.timer_start(timer, 100, 100, function () end) uv.timer_stop(timer) uv.close(timer, function () end) uv.run() end) end) test("lots-o-timers with real timeouts", function (print, p, expect, uv) bench(uv, p, 0x500, function () local timer = uv.new_timer() uv.timer_start(timer, 10, 0, expect(function () uv.timer_stop(timer) uv.close(timer, function () end) end)) end) end) test("reading file async", function (print, p, expect, uv) local mode = tonumber("644", 8) bench(uv, p, 0x500, function () local onOpen, onStat, onRead, onClose local fd, stat onOpen = expect(function (err, result) assert(not err, err) fd = result uv.fs_fstat(fd, onStat) end) onStat = expect(function (err, result) assert(not err, err) stat = result uv.fs_read(fd, stat.size, 0, onRead) end) onRead = expect(function (err, data) assert(not err, err) assert(#data == stat.size) uv.fs_close(fd, onClose) end) onClose = expect(function (err) assert(not err, err) end) assert(uv.fs_open("README.md", "r", mode, onOpen)) end) end) test("reading file sync", function (print, p, expect, uv) local mode = tonumber("644", 8) bench(uv, p, 0x2000, function () local fd = assert(uv.fs_open("README.md", "r", mode)) local stat = assert(uv.fs_fstat(fd)) local data = assert(uv.fs_read(fd, stat.size, 0)) assert(#data == stat.size) assert(uv.fs_close(fd)) end) end) test("invalid file", function (print, p, expect, uv) local mode = tonumber("644", 8) bench(uv, p, 0x1500, function () local req = uv.fs_open("BAD_FILE", "r", mode, expect(function (err, fd) assert(not fd) assert(err) end)) end) end) test("invalid file sync", function (print, p, expect, uv) local mode = tonumber("644", 8) bench(uv, p, 0x20000, function () local fd, err = uv.fs_open("BAD_FILE", "r", mode) assert(not fd) assert(err) end) end) test("invalid spawn args", function (print, p, expect, uv) -- Regression test for #73 bench(uv, p, 0x10000, function () local ret, err = pcall(function () return uv.spawn("ls", { args = {"-l", "-h"}, stdio = {0, 1, 2}, env = {"EXTRA=true"}, gid = false, -- Should be integer }) end) assert(not ret) assert(err) end) end) test("stream writing with string and array", function (print, p, expect, uv) local port = 0 local server = uv.new_tcp() local data local count = 0x800 server:unref() server:bind("127.0.0.1", port) server:listen(128, expect(function (err) assert(not err, err) local client = uv.new_tcp() server:accept(client) client:write(data) client:read_start(expect(function (err, data) assert(not err, err) assert(data) client:close() end)) end, count)) local address = server:getsockname() bench(uv, p, count, function () data = string.rep("Hello", 500) local socket = uv.new_tcp() socket:connect(address.ip, address.port, expect(function (err) assert(not err, err) socket:read_start(expect(function (err, chunk) assert(not err, err) assert(chunk) local data = {} for i = 0, 100 do data[i + 1] = string.rep(string.char(i), 100) end socket:write(data) socket:close() end)) end)) uv.run() end) server:close() end) test("test nil handle for writes", function(print, p, expect, uv) local ret, err = pcall(function () uv.write(nil, "hello") end) assert(not ret) assert(err) end) end) luv-1.36.0-0/tests/run.lua000066400000000000000000000006631364617304100152270ustar00rootroot00000000000000-- Run this from the parent directory as -- -- luajit tests/run.lua -- local tap = require("lib/tap") local uv = require("luv") local req = uv.fs_scandir("tests") while true do local name = uv.fs_scandir_next(req) if not name then break end local match = string.match(name, "^test%-(.*).lua$") if match then local path = "tests/test-" .. match tap(match) require(path) end end -- run the tests! tap(true) luv-1.36.0-0/tests/test-async.lua000066400000000000000000000017401364617304100165120ustar00rootroot00000000000000return require('lib/tap')(function (test) test("test pass async between threads", function(p, p, expect, uv) local before = os.time() local async async = uv.new_async(expect(function (a,b,c) p('in async notify callback') p(a,b,c) assert(a=='a') assert(b==true) assert(c==250) uv.close(async) end)) local args = {500, 'string', nil, false, 5, "helloworld",async} local unpack = unpack or table.unpack uv.new_thread(function(num,s,null,bool,five,hw,asy) local uv = require'luv' assert(type(num) == "number") assert(type(s) == "string") assert(null == nil) assert(bool == false) assert(five == 5) assert(hw == 'helloworld') assert(type(asy)=='userdata') assert(uv.async_send(asy,'a',true,250)==0) uv.sleep(1000) end, unpack(args)):join() local elapsed = (os.time() - before) * 1000 assert(elapsed >= 1000, "elapsed should be at least delay ") end) end) luv-1.36.0-0/tests/test-callbacks.lua000066400000000000000000000032601364617304100173130ustar00rootroot00000000000000return require('lib/tap')(function (test) -- Notes: -- * When using a callable table as a callback, it will get itself as the first param when it is called. -- This matches what happens when calling the callable table normally. -- * expect wraps its argument in a function and returns the function, so expect should not be called on -- a callable table directly. test("luv_handle_t: function", function (print, p, expect, uv) local handle = uv.new_timer() local function onclose() p("closed", handle) end local function ontimeout() p("timeout", handle) uv.close(handle, expect(onclose)) end uv.timer_start(handle, 10, 0, expect(ontimeout)) end) test("luv_handle_t: callable table", function (print, p, expect, uv) local handle = uv.new_timer() local function onclose(self) p("closed", self, handle) end local onCloseTable = setmetatable({}, {__call=expect(onclose)}) local function ontimeout(self) p("timeout", self, handle) uv.close(handle, onCloseTable) end local onTimeoutTable = setmetatable({}, {__call=expect(ontimeout)}) uv.timer_start(handle, 10, 0, onTimeoutTable) end) test("luv_req_t: function", function (print, p, expect, uv) local fn = function(err, stat) assert(not err) assert(stat) end assert(uv.fs_stat('.', expect(fn))) end) test("luv_req_t: callable table", function (print, p, expect, uv) local callable local fn = function(self, err, stat) assert(self == callable) assert(not err, err) assert(stat) end callable = setmetatable({}, {__call=expect(fn)}) assert(uv.fs_stat('.', callable)) end) end)luv-1.36.0-0/tests/test-conversions.lua000066400000000000000000000004741364617304100177500ustar00rootroot00000000000000return require('lib/tap')(function (test) test("basic 64bit conversions", function (print, p, expect, uv) if _VERSION=='Lua 5.3' then assert(string.format("%x", 29913653248) == "6f6fe2000") assert(string.format("%x", 32207650816) == "77fb9c000") else print('skipped') end end) end) luv-1.36.0-0/tests/test-coroutines.lua000066400000000000000000000012341364617304100175650ustar00rootroot00000000000000return require('lib/tap')(function (test) test("coroutines", function (print, p, expect, uv) local touch = 0 local function wait(ms) local this = coroutine.running() assert(this) local timer = uv.new_timer() timer:start(ms, 0, function () timer:close() touch = touch + 1 coroutine.resume(this) touch = touch + 1 end) coroutine.yield() touch = touch + 1 return touch end coroutine.wrap(function() print("begin wait") local touched = wait(1000) assert(touched==touch) print("end wait") end)() uv.run() assert(touch==3) end) end) luv-1.36.0-0/tests/test-dns.lua000066400000000000000000000111441364617304100161600ustar00rootroot00000000000000return require('lib/tap')(function (test) local isWindows = require('lib/utils').isWindows local function errorAllowed(err) -- allowed errors from gnulib's test-getaddrinfo.c return err == "EAI_AGAIN" -- offline/no network connection or err == "EAI_NONAME" -- IRIX returns this for "https" or err == "EAI_SERVICE" -- Solaris returns this for "http"/"https" or err == "EAI_NODATA" -- AIX returns this for "https" end test("Get all local http addresses", function (print, p, expect, uv) assert(uv.getaddrinfo(nil, "http", nil, expect(function (err, res) if errorAllowed(err) then print(err, "skipping") return end assert(not err, err) p(res, #res) assert(res[1].port == 80) end))) end) test("Get all local http addresses sync", function (print, p, expect, uv) local res, errstr, err = uv.getaddrinfo(nil, "http") if errorAllowed(err) then print(err, "skipping") return end assert(res, errstr) p(res, #res) assert(res[1].port == 80) end, "1.3.0") test("Get only ipv4 tcp adresses for luvit.io", function (print, p, expect, uv) assert(uv.getaddrinfo("luvit.io", nil, { socktype = "stream", family = "inet", }, expect(function (err, res) if errorAllowed(err) then print(err, "skipping") return end assert(not err, err) p(res, #res) assert(#res > 0) end))) end) -- FIXME: this test always fails on AppVeyor for some reason if isWindows and not os.getenv'APPVEYOR' then test("Get only ipv6 tcp adresses for luvit.io", function (print, p, expect, uv) assert(uv.getaddrinfo("luvit.io", nil, { socktype = "stream", family = "inet6", }, expect(function (err, res) if errorAllowed(err) then print(err, "skipping") return end assert(not err, err) p(res, #res) assert(#res == 1) end))) end) end test("Get ipv4 and ipv6 tcp adresses for luvit.io", function (print, p, expect, uv) assert(uv.getaddrinfo("luvit.io", nil, { socktype = "stream", }, expect(function (err, res) if errorAllowed(err) then print(err, "skipping") return end assert(not err, err) p(res, #res) assert(#res > 0) end))) end) test("Get all adresses for luvit.io", function (print, p, expect, uv) assert(uv.getaddrinfo("luvit.io", nil, nil, expect(function (err, res) if errorAllowed(err) then print(err, "skipping") return end assert(not err, err) p(res, #res) assert(#res > 0) end))) end) test("Lookup local ipv4 address", function (print, p, expect, uv) assert(uv.getnameinfo({ family = "inet", }, expect(function (err, hostname, service) if errorAllowed(err) then print(err, "skipping") return end p{err=err,hostname=hostname,service=service} assert(not err, err) assert(hostname) assert(service) end))) end) test("Lookup local ipv4 address sync", function (print, p, expect, uv) local hostname, service, err = uv.getnameinfo({ family = "inet", }) if errorAllowed(err) then print(err, "skipping") return end p{hostname=hostname,service=service} assert(hostname) assert(service) end, "1.3.0") test("Lookup local 127.0.0.1 ipv4 address", function (print, p, expect, uv) assert(uv.getnameinfo({ ip = "127.0.0.1", }, expect(function (err, hostname, service) p{err=err,hostname=hostname,service=service} assert(not err, err) assert(hostname) assert(service) end))) end) test("Lookup local ipv6 address", function (print, p, expect, uv) assert(uv.getnameinfo({ family = "inet6", }, expect(function (err, hostname, service) p{err=err,hostname=hostname,service=service} assert(not err, err) assert(hostname) assert(service) end))) end) test("Lookup local ::1 ipv6 address", function (print, p, expect, uv) assert(uv.getnameinfo({ ip = "::1", }, expect(function (err, hostname, service) p{err=err,hostname=hostname,service=service} assert(not err, err) assert(hostname) assert(service) end))) end) test("Lookup local port 80 service", function (print, p, expect, uv) assert(uv.getnameinfo({ port = 80, family = "inet6", }, expect(function (err, hostname, service) p{err=err,hostname=hostname,service=service} assert(not err, err) assert(hostname) assert(service == "http") end))) end) end) luv-1.36.0-0/tests/test-fs.lua000066400000000000000000000216661364617304100160160ustar00rootroot00000000000000return require('lib/tap')(function (test) test("read a file sync", function (print, p, expect, uv) local fd = assert(uv.fs_open('README.md', 'r', tonumber('644', 8))) p{fd=fd} local stat = assert(uv.fs_fstat(fd)) p{stat=stat} local chunk = assert(uv.fs_read(fd, stat.size, 0)) assert(#chunk == stat.size) assert(uv.fs_close(fd)) end) test("read a file async", function (print, p, expect, uv) uv.fs_open('README.md', 'r', tonumber('644', 8), expect(function (err, fd) assert(not err, err) p{fd=fd} uv.fs_fstat(fd, expect(function (err, stat) assert(not err, err) p{stat=stat} uv.fs_read(fd, stat.size, 0, expect(function (err, chunk) assert(not err, err) p{chunk=#chunk} assert(#chunk == stat.size) uv.fs_close(fd, expect(function (err) assert(not err, err) end)) end)) end)) end)) end) test("fs.write", function (print, p, expect, uv) local path = "_test_" local fd = assert(uv.fs_open(path, "w", 438)) uv.fs_write(fd, "Hello World\n", -1) uv.fs_write(fd, {"with\n", "more\n", "lines\n"}, -1) uv.fs_close(fd) uv.fs_unlink(path) end) -- collect garbage after uv.fs_write but before the write callback -- is called in order to potentially garbage collect the strings that -- are being sent. See https://github.com/luvit/luv/issues/397 test("fs.write data refs", function (print, p, expect, uv) local path = "_test_" local fd = assert(uv.fs_open(path, "w+", tonumber("0666", 8))) do -- the number here gets coerced into a string local t = {"with", 600, "lines"} uv.fs_write(fd, t, -1, function() local expectedContents = table.concat(t) local stat = assert(uv.fs_fstat(fd)) assert(stat.size == #expectedContents) local chunk = assert(uv.fs_read(fd, stat.size, 0)) assert(chunk == expectedContents) assert(uv.fs_close(fd)) assert(uv.fs_unlink(path)) end) end local count = collectgarbage("count") collectgarbage("collect") assert(count - collectgarbage("count") > 0) end) test("fs.stat sync", function (print, p, expect, uv) local stat = assert(uv.fs_stat("README.md")) assert(stat.size) end) test("fs.stat async", function (print, p, expect, uv) assert(uv.fs_stat("README.md", expect(function (err, stat) assert(not err, err) assert(stat.size) end))) end) test("fs.stat sync error", function (print, p, expect, uv) local stat, err, code = uv.fs_stat("BAD_FILE!") p{err=err,code=code,stat=stat} assert(not stat) assert(err) assert(code == "ENOENT") end) test("fs.stat async error", function (print, p, expect, uv) assert(uv.fs_stat("BAD_FILE@", expect(function (err, stat) p{err=err,stat=stat} assert(err) assert(not stat) end))) end) test("fs.scandir", function (print, p, expect, uv) local req = uv.fs_scandir('.') local function iter() return uv.fs_scandir_next(req) end for name, ftype in iter do p{name=name, ftype=ftype} assert(name) -- ftype is not available in all filesystems; for example it's -- provided for HFS+ (OSX), NTFS (Windows) but not for ext4 (Linux). end end) test("fs.realpath", function (print, p, expect, uv) p(assert(uv.fs_realpath('.'))) assert(uv.fs_realpath('.', expect(function (err, path) assert(not err, err) p(path) end))) end, "1.8.0") test("fs.copyfile", function (print, p, expect, uv) local path = "_test_" local path2 = "_test2_" local fd = assert(uv.fs_open(path, "w", 438)) uv.fs_write(fd, "Hello World\n", -1) uv.fs_close(fd) assert(uv.fs_copyfile(path, path2)) assert(uv.fs_unlink(path)) assert(uv.fs_unlink(path2)) end, "1.14.0") test("fs.{open,read,close}dir object sync #1", function(print, p, expect, uv) local dir = assert(uv.fs_opendir('.')) repeat local dirent = dir:readdir() if dirent then assert(#dirent==1) p(dirent) end until not dirent assert(dir:closedir()==true) end, "1.28.0") test("fs.{open,read,close}dir object sync #2", function(print, p, expect, uv) local dir = assert(uv.fs_opendir('.')) repeat local dirent = dir:readdir() if dirent then assert(#dirent==1) p(dirent) end until not dirent dir:closedir(function(err, state) assert(err==nil) assert(state==true) assert(tostring(dir):match("^uv_dir_t")) print(dir, 'closed') end) end, "1.28.0") test("fs.{open,read,close}dir sync one entry", function(print, p, expect, uv) local dir = assert(uv.fs_opendir('.')) repeat local dirent = uv.fs_readdir(dir) if dirent then assert(#dirent==1) p(dirent) end until not dirent assert(uv.fs_closedir(dir)==true) end, "1.28.0") test("fs.{open,read,close}dir sync more entry", function(print, p, expect, uv) local dir = assert(uv.fs_opendir('.', nil, 50)) repeat local dirent = uv.fs_readdir(dir) if dirent then p(dirent) end until not dirent assert(uv.fs_closedir(dir)==true) end, "1.28.0") test("fs.{open,read,close}dir with more entry", function(print, p, expect, uv) local function opendir_cb(err, dir) assert(not err) local function readdir_cb(err, dirs) assert(not err) if dirs then p(dirs) uv.fs_readdir(dir, readdir_cb) else assert(uv.fs_closedir(dir)==true) end end uv.fs_readdir(dir, readdir_cb) end assert(uv.fs_opendir('.', opendir_cb, 50)) end, "1.28.0") test("fs.statfs sync", function (print, p, expect, uv) local stat = assert(uv.fs_statfs(".")) p(stat) assert(stat.bavail>0) end, "1.31.0") test("fs.statfs async", function (print, p, expect, uv) assert(uv.fs_statfs(".", expect(function (err, stat) assert(not err, err) p(stat) assert(stat.bavail>0) end))) end, "1.31.0") test("fs.statfs sync error", function (print, p, expect, uv) local stat, err, code = uv.fs_statfs("BAD_FILE!") p{err=err,code=code,stat=stat} assert(not stat) assert(err) assert(code == "ENOENT") end, "1.31.0") test("fs.statfs async error", function (print, p, expect, uv) assert(uv.fs_statfs("BAD_FILE@", expect(function (err, stat) p{err=err,stat=stat} assert(err) assert(not stat) end))) end, "1.31.0") test("fs.mkdtemp async", function(print, p, expect, uv) local tp = "luvXXXXXX" uv.fs_mkdtemp(tp, function(err, path) assert(not err) assert(path:match("^luv......")) assert(uv.fs_rmdir(path)) end) end) test("fs.mkdtemp sync", function(print, p, expect, uv) local tp = "luvXXXXXX" local path, err, code = uv.fs_mkdtemp(tp) assert(path:match("^luv......")) assert(uv.fs_rmdir(path)) end) test("fs.mkdtemp async error", function(print, p, expect, uv) local tp = "luvXXXXXZ" uv.fs_mkdtemp(tp, function(err, path) -- Will success on MacOS if not err then assert(path:match("^luv......")) assert(uv.fs_rmdir(path)) else assert(err:match("^EINVAL:")) assert(path==nil) end end) end) test("fs.mkdtemp sync error", function(print, p, expect, uv) local tp = "luvXXXXXZ" local path, err, code = uv.fs_mkdtemp(tp) -- Will success on MacOS if not err then assert(path:match("^luv......")) assert(uv.fs_rmdir(path)) else assert(path==nil) assert(err:match("^EINVAL:")) assert(code=='EINVAL') end end) test("fs.mkstemp async", function(print, p, expect, uv) local tp = "luvXXXXXX" uv.fs_mkstemp(tp, function(err, fd, path) assert(not err) assert(type(fd)=='number') assert(path:match("^luv......")) assert(uv.fs_close(fd)) assert(uv.fs_unlink(path)) end) end, "1.34.0") test("fs.mkstemp sync", function(print, p, expect, uv) local tp = "luvXXXXXX" local content = "hello world!" local fd, path = uv.fs_mkstemp(tp) assert(type(fd)=='number') assert(path:match("^luv......")) uv.fs_write(fd, content, -1) assert(uv.fs_close(fd)) fd = assert(uv.fs_open(path, "r", 438)) local stat = assert(uv.fs_fstat(fd)) local chunk = assert(uv.fs_read(fd, stat.size, 0)) assert(#chunk == stat.size) assert(chunk==content) assert(uv.fs_close(fd)) assert(uv.fs_unlink(path)) end, "1.34.0") test("fs.mkstemp async error", function(print, p, expect, uv) local tp = "luvXXXXXZ" uv.fs_mkstemp(tp, function(err, path, fd) assert(err:match("^EINVAL:")) assert(path==nil) assert(fd==nil) end) end, "1.34.0") test("fs.mkstemp sync error", function(print, p, expect, uv) local tp = "luvXXXXXZ" local path, err, code = uv.fs_mkstemp(tp) assert(path==nil) assert(err:match("^EINVAL:")) assert(code=='EINVAL') end, "1.34.0") end) luv-1.36.0-0/tests/test-misc.lua000066400000000000000000000106351364617304100163330ustar00rootroot00000000000000return require('lib/tap')(function (test) test("uv.guess_handle", function (print, p, expect, uv) local types = { [0] = assert(uv.guess_handle(0)), assert(uv.guess_handle(1)), assert(uv.guess_handle(2)), } p("stdio fd types", types) end) test("uv.version and uv.version_string", function (print, p, expect, uv) local version = assert(uv.version()) local version_string = assert(uv.version_string()) p{version=version, version_string=version_string} assert(type(version) == "number") assert(type(version_string) == "string") end) test("memory size", function (print, p, expect, uv) local rss = uv.resident_set_memory() local total = uv.get_total_memory() local constrained = nil if uv.get_constrained_memory then constrained = uv.get_constrained_memory() end local free = uv.get_free_memory() p{rss=rss,total=total,free=free, constrained=constrained} assert(rss < total) end) test("uv.uptime", function (print, p, expect, uv) local uptime = assert(uv.uptime()) p{uptime=uptime} end) test("uv.getrusage", function (print, p, expect, uv) local rusage = assert(uv.getrusage()) p(rusage) end) test("uv.cpu_info", function (print, p, expect, uv) local info = assert(uv.cpu_info()) p(info) end) test("uv.interface_addresses", function (print, p, expect, uv) local addresses = assert(uv.interface_addresses()) for name, info in pairs(addresses) do p(name, addresses[name]) end end) test("uv.loadavg", function (print, p, expect, uv) local avg = {assert(uv.loadavg())} p(avg) assert(#avg == 3) end) test("uv.exepath", function (print, p, expect, uv) local path = assert(uv.exepath()) p(path) end) test("uv.os_homedir", function (print, p, expect, uv) local path = assert(uv.os_homedir()) p(path) end, "1.9.0") test("uv.os_tmpdir", function (print, p, expect, uv) local path = assert(uv.os_tmpdir()) p(path) end, "1.9.0") test("uv.os_get_passwd", function (print, p, expect, uv) local passwd = assert(uv.os_get_passwd()) p(passwd) end, "1.9.0") test("uv.cwd and uv.chdir", function (print, p, expect, uv) local old = assert(uv.cwd()) p(old) assert(uv.chdir("/")) local cwd = assert(uv.cwd()) p(cwd) assert(cwd ~= old) assert(uv.chdir(old)) end) test("uv.hrtime", function (print, p, expect, uv) local time = assert(uv.hrtime()) p(time) end) test("uv.getpid", function (print, p, expect, uv) assert(uv.getpid()) end) test("uv.os_uname", function(print, p, expect, uv) local uname = assert(uv.os_uname()) p(uname) end, "1.25.0") test("uv.gettimeofday", function(print, p, expect, uv) local now = os.time() local sec, usec = assert(uv.gettimeofday()) print(' os.time', now) print('uv.gettimeofday',string.format("%f",sec+usec/10^9)) assert(type(sec)=='number') assert(type(usec)=='number') end, "1.28.0") test("uv.os_environ", function(print, p, expect, uv) local name, name2 = "LUV_TEST_FOO", "LUV_TEST_FOO2"; local value, value2 = "123456789", "" assert(uv.os_setenv(name, value)) assert(uv.os_setenv(name2, value2)) local env = uv.os_environ(); assert(env[name]==value) assert(env[name2]==value2) end, "1.31.0") test("uv.sleep", function(print, p, expect, uv) local val = 1000 local begin = uv.now() uv.sleep(val) uv.update_time() local now = uv.now() assert(now-begin >= val) end) test("uv.random async", function(print, p, expect, uv) local len = 256 assert(uv.random(len, {}, expect(function(err, randomBytes) assert(not err) assert(#randomBytes == len) -- this matches the LibUV test -- it can theoretically fail but its very unlikely assert(randomBytes ~= string.rep("\0", len)) end))) end, "1.33.0") test("uv.random sync", function(print, p, expect, uv) local len = 256 local randomBytes = assert(uv.random(len)) assert(#randomBytes == len) -- this matches the LibUV test -- it can theoretically fail but its very unlikely assert(randomBytes ~= string.rep("\0", len)) end, "1.33.0") test("uv.random errors", function(print, p, expect, uv) -- invalid flag local _, err = uv.random(0, -1) assert(err:match("^EINVAL")) -- invalid len _, err = uv.random(-1) assert(err:match("^E2BIG")) end, "1.33.0") end) luv-1.36.0-0/tests/test-prepare-check-idle-async.lua000066400000000000000000000022611364617304100221330ustar00rootroot00000000000000return require('lib/tap')(function (test) test("simple prepare", function (print, p, expect, uv) local prepare = uv.new_prepare() uv.prepare_start(prepare, expect(function () p("prepare", prepare) uv.prepare_stop(prepare) uv.close(prepare, expect(function () end)) end)) end) test("simple check", function (print, p, expect, uv) local check = uv.new_check() uv.check_start(check, expect(function () p("check", check) uv.check_stop(check) uv.close(check, expect(function () end)) end)) -- Trigger with a timer local timer = uv.new_timer() uv.timer_start(timer, 10, 0, expect(function() p("timeout", timer) uv.timer_stop(timer) uv.close(timer) end)) end) test("simple idle", function (print, p, expect, uv) local idle = uv.new_idle() uv.idle_start(idle, expect(function () p("idle", idle) uv.idle_stop(idle) uv.close(idle, expect(function () end)) end)) end) test("simple async", function (print, p, expect, uv) local async async = uv.new_async(expect(function () uv.close(async) end)) uv.async_send(async) end) end) luv-1.36.0-0/tests/test-process.lua000066400000000000000000000067711364617304100170640ustar00rootroot00000000000000return require('lib/tap')(function (test) local isWindows = require('lib/utils').isWindows test("test disable_stdio_inheritance", function (print, p, expect, uv) uv.disable_stdio_inheritance() end) test("process stdout", function (print, p, expect, uv) local stdout = uv.new_pipe(false) local input = "Hello World" local cmd, args, expectedOutput if isWindows then cmd = "cmd.exe" args = {"/c", "echo "..input} expectedOutput = input .. "\r\n" else cmd = "echo" args = {input} expectedOutput = input .. "\n" end local handle, pid handle, pid = uv.spawn(cmd, { args = args, stdio = {nil, stdout}, }, expect(function (code, signal) p("exit", {code=code, signal=signal}) uv.close(handle) end)) p{ handle=handle, pid=pid } uv.read_start(stdout, expect(function (err, chunk) p("stdout", {err=err,chunk=chunk}) assert(not err, err) assert(chunk == expectedOutput) uv.close(stdout) end)) end) local longRunning = {} if isWindows then longRunning.cmd = "cmd.exe" longRunning.options = { args = {"/c","pause"} } longRunning.expect_status = 1 else longRunning.cmd = 'sleep' longRunning.options = { args = {1} } longRunning.expect_status = 0 end test("spawn and kill by pid", function (print, p, expect, uv) local handle, pid handle, pid = uv.spawn(longRunning.cmd, longRunning.options, expect(function (status, signal) p("exit", handle, {status=status,signal=signal}) assert(status == longRunning.expect_status) if isWindows then -- just call TerminateProcess, ref uv__kill in libuv/src/win/process.c assert(signal == 0) else assert(signal == 2) end uv.close(handle) end)) p{handle=handle,pid=pid} uv.kill(pid, "sigint") end) test("spawn and kill by handle", function (print, p, expect, uv) local handle, pid handle, pid = uv.spawn(longRunning.cmd, longRunning.options, expect(function (status, signal) p("exit", handle, {status=status,signal=signal}) assert(status == longRunning.expect_status) assert(signal == 15) uv.close(handle) end)) p{handle=handle,pid=pid} uv.process_kill(handle, "sigterm") end) test("invalid command", function (print, p, expect, uv) local handle, err handle, err = uv.spawn("ksjdfksjdflkjsflksdf", {}, function(exit, code) assert(false) end) assert(handle == nil) assert(err) end) test("process stdio", function (print, p, expect, uv) local stdin = uv.new_pipe(false) local stdout = uv.new_pipe(false) local input = "Hello World" local cmd, args, expectedOutput if isWindows then cmd = "cmd.exe" args = {"/c", "set /p output=&call echo %output%"} expectedOutput = input .. "\r\n" else cmd = "cat" args = {"-"} expectedOutput = input end local handle, pid handle, pid = uv.spawn(cmd, { args = args, stdio = {stdin, stdout}, }, expect(function (code, signal) p("exit", {code=code, signal=signal}) uv.close(handle) end)) p{ handle=handle, pid=pid } uv.read_start(stdout, expect(function (err, chunk) p("stdout", {err=err,chunk=chunk}) assert(not err, err) assert(chunk == expectedOutput) uv.close(stdout) end)) uv.write(stdin, input) uv.shutdown(stdin, expect(function () uv.close(stdin) end)) end) end) luv-1.36.0-0/tests/test-sigchld-after-lua_close.sh000077500000000000000000000024571364617304100217170ustar00rootroot00000000000000#!/bin/sh # Verifies that luv will cleanup libuv process handles correctly even if # not done by "userspace". # Details: https://github.com/luvit/luv/issues/193 set -e # This test modifies one of the examples to skip libuv process cleanup, # purposely making it leave SIGCHLD signal handler. # patch -p1 << "EOF" diff --git a/examples/talking-to-children.lua b/examples/talking-to-children.lua index 10a53ef..6c6c53f 100644 --- a/examples/talking-to-children.lua +++ b/examples/talking-to-children.lua @@ -41,7 +41,3 @@ uv.read_start(stdout, onread) uv.read_start(stderr, onread) uv.write(stdin, "Hello World") uv.shutdown(stdin, onshutdown) - -uv.run() -uv.walk(uv.close) -uv.run() EOF # It also requires a patched lua standalone interpreter that sends SIGCHLD to # itself after calling lua_close, which would have freed all memory of the libuv # event loop associated with the lua state. ( cd deps/lua patch -p1 << "EOF" diff --git a/lua.c b/lua.c index 7a47582..4dc19d5 100644 --- a/lua.c +++ b/lua.c @@ -608,6 +608,7 @@ int main (int argc, char **argv) { result = lua_toboolean(L, -1); /* get result */ report(L, status); lua_close(L); + kill(0, SIGCHLD); return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; } EOF ) WITH_LUA_ENGINE=Lua make ./build/lua examples/talking-to-children.lua luv-1.36.0-0/tests/test-signal.lua000066400000000000000000000023271364617304100166540ustar00rootroot00000000000000local child_code = string.dump(function () local uv = require('luv') local signal = uv.new_signal() uv.ref(signal) uv.signal_start(signal, "sigint", function () print("sigint") uv.unref(signal) end) uv.run() end) return require('lib/tap')(function (test) if require('lib/utils').isWindows then return end test("Catch SIGINT", function (print, p, expect, uv) local child, pid local input = uv.new_pipe(false) local output = uv.new_pipe(false) child, pid = assert(uv.spawn(uv.exepath(), { args = {"-"}, stdio = {input,output,2} }, expect(function (code, signal) p("exit", {pid=pid,code=code,signal=signal}) assert(signal == 0) uv.close(input) uv.close(output) uv.close(child) end))) uv.read_start(output, expect(function(err, chunk) assert(not err, err) if chunk then p(chunk) assert(chunk=="sigint\n") uv.read_stop(output) end end, 1)) uv.write(input, child_code) uv.shutdown(input) local timer = uv.new_timer() uv.timer_start(timer, 200, 0, expect(function () print("Sending child SIGINT") uv.process_kill(child, "sigint") uv.close(timer) end)) end) end) luv-1.36.0-0/tests/test-tcp.lua000066400000000000000000000233501364617304100161640ustar00rootroot00000000000000return require('lib/tap')(function (test) test("basic tcp server and client (ipv4)", function (print, p, expect, uv) local server = uv.new_tcp() assert(uv.tcp_bind(server, "127.0.0.1", 0)) assert(uv.listen(server, 128, expect(function (err) p("server on connection", server) assert(not err, err) uv.close(server) end))) local address = uv.tcp_getsockname(server) p{server=server,address=address} local client = uv.new_tcp() local req = assert(uv.tcp_connect(client, "127.0.0.1", address.port, expect(function (err) p("client on connect", client, err) assert(not err, err) uv.shutdown(client, expect(function (err) p("client on shutdown", client, err) assert(not err, err) uv.close(client, expect(function () p("client on close", client) end)) end)) end))) p{client=client,req=req} end) test("basic tcp server and client (ipv6)", function (print, p, expect, uv) local server = uv.new_tcp() local _, err = uv.tcp_bind(server, "::1", 0) if err then p("ipv6 unavailable", err) uv.close(server) return end assert(uv.listen(server, 128, expect(function (err) p("server on connection", server) assert(not err, err) uv.close(server) end))) local address = uv.tcp_getsockname(server) p{server=server,address=address} local client = uv.new_tcp() local req = assert(uv.tcp_connect(client, "::1", address.port, expect(function (err) p("client on connect", client, err) assert(not err, err) uv.shutdown(client, expect(function (err) p("client on shutdown", client, err) assert(not err, err) uv.close(client, expect(function () p("client on close", client) end)) end)) end))) p{client=client,req=req} end) test("tcp echo server and client", function (print, p, expect, uv) local server = uv.new_tcp() assert(uv.tcp_bind(server, "127.0.0.1", 0)) assert(uv.listen(server, 1, expect(function () local client = uv.new_tcp() assert(uv.accept(server, client)) assert(uv.read_start(client, expect(function (err, data) p("server read", {err=err,data=data}) assert(not err, err) if data then assert(uv.write(client, data)) else assert(uv.read_stop(client)) uv.close(client) uv.close(server) end end, 2))) end))) local address = uv.tcp_getsockname(server) p{server=server,address=address} local socket = assert(uv.new_tcp()) assert(uv.tcp_connect(socket, "127.0.0.1", address.port, expect(function () assert(uv.read_start(socket, expect(function (err, data) p("client read", {err=err,data=data}) assert(not err, err) assert(uv.read_stop(socket)) uv.close(socket) end))) local req = assert(uv.write(socket, "Hello", function (err) p("client onwrite", socket, err) assert(not err, err) end)) p{socket=socket,req=req} end))) end) test("tcp echo server and client with methods", function (print, p, expect, uv) local server = uv.new_tcp() assert(server:bind("127.0.0.1", 0)) assert(server:listen(1, expect(function () local client = uv.new_tcp() assert(server:accept(client)) assert(client:read_start(expect(function (err, data) p("server read", {err=err,data=data}) assert(not err, err) if data then assert(client:write(data)) else assert(client:read_stop()) client:close() server:close() end end, 2))) end))) local address = server:getsockname() p{server=server,address=address} local socket = assert(uv.new_tcp()) assert(socket:connect("127.0.0.1", address.port, expect(function () assert(socket:read_start(expect(function (err, data) p("client read", {err=err,data=data}) assert(not err, err) assert(socket:read_stop()) socket:close() end))) local req = assert(socket:write("Hello", function (err) p("client onwrite", socket, err) assert(not err, err) end)) p{socket=socket,req=req} end))) end) test("tcp invalid ip address", function (print, p, expect, uv) local ip = '127.0.0.100005' local server = uv.new_tcp() local status, err = pcall(function() uv.tcp_bind(server, ip, 1000) end) assert(not status) p(err) assert(err:find(ip)) uv.close(server) end) test("tcp close reset client", function(print, p, expect, uv) local server = uv.new_tcp() assert(uv.tcp_bind(server, "127.0.0.1", 0)) assert(uv.listen(server, 1, expect(function () local client = uv.new_tcp() assert(uv.accept(server, client)) assert(uv.read_start(client, expect(function (err, data) p("server read", {err=err,data=data}) if data then assert(uv.write(client, data)) else assert(err=='ECONNRESET') assert(uv.read_stop(client)) uv.close(client) uv.close(server) end end, 2))) end))) local address = uv.tcp_getsockname(server) p{server=server,address=address} local socket = assert(uv.new_tcp()) assert(uv.tcp_connect(socket, "127.0.0.1", address.port, expect(function () assert(uv.read_start(socket, expect(function (err, data) p("client read", {err=err,data=data}) assert(not err, err) assert(uv.read_stop(socket)) uv.tcp_close_reset(socket, expect(function() assert(uv.is_closing(socket)) _, err = uv.shutdown(socket) assert(err:find('^ENOTCONN')) end)) end))) local req = assert(uv.write(socket, "Hello", function (err) p("client onwrite", socket, err) assert(not err, err) end)) p{socket=socket,req=req} end))) end, "1.32.0") test("tcp close reset after shutdown", function(print, p, expect, uv) local server = uv.new_tcp() assert(uv.tcp_bind(server, "127.0.0.1", 0)) assert(uv.listen(server, 1, expect(function () local client = uv.new_tcp() assert(uv.accept(server, client)) assert(uv.read_start(client, expect(function (err, data) p("server read", {err=err,data=data}) if data then assert(uv.write(client, data)) else assert(uv.read_stop(client)) uv.close(client) uv.close(server) end end, 2))) end))) local address = uv.tcp_getsockname(server) p{server=server,address=address} local socket = assert(uv.new_tcp()) assert(uv.tcp_connect(socket, "127.0.0.1", address.port, expect(function () assert(uv.read_start(socket, expect(function (err, data) p("client read", {err=err,data=data}) assert(not err, err) assert(uv.read_stop(socket)) uv.shutdown(socket, expect(function() uv.close(socket) end)) _, err = uv.tcp_close_reset(socket) assert(err:find('^EINVAL')) end))) local req = assert(uv.write(socket, "Hello", function (err) p("client onwrite", socket, err) assert(not err, err) end)) p{socket=socket,req=req} end))) end, "1.32.0") test("tcp close reset accepted", function(print, p, expect, uv) local server = uv.new_tcp() assert(uv.tcp_bind(server, "127.0.0.1", 0)) assert(uv.listen(server, 1, expect(function () local client = uv.new_tcp() assert(uv.accept(server, client)) assert(uv.read_start(client, function (err, data) p("server read", {err=err,data=data}) assert(uv.read_stop(client)) if data then assert(uv.write(client, data, function() client:close_reset(function() server:close() end) end)) end end)) end))) local address = uv.tcp_getsockname(server) p{server=server,address=address} local socket = assert(uv.new_tcp()) assert(uv.tcp_connect(socket, "127.0.0.1", address.port, expect(function () assert(uv.read_start(socket,function (err, data) p("client read", {err=err,data=data}) if not data then assert(err=='ECONNRESET' or err==nil) uv.close(socket) end end)) local req = assert(uv.write(socket, "Hello", function (err) p("client onwrite", socket, err) assert(not err, err) end)) p{socket=socket,req=req} end))) end, "1.32.0") test("tcp close reset accepted after shutdown", function(print, p, expect, uv) local server = uv.new_tcp() assert(uv.tcp_bind(server, "127.0.0.1", 0)) assert(uv.listen(server, 1, expect(function () local client = uv.new_tcp() assert(uv.accept(server, client)) assert(uv.read_start(client, expect(function (err, data) p("server read", {err=err,data=data}) if data then assert(uv.write(client, data, expect(function() uv.shutdown(client, function() end) _, err = uv.tcp_close_reset(client) assert(err:find('^EINVAL')) end))) else uv.close(client) uv.close(server) end end, 2))) end))) local address = uv.tcp_getsockname(server) p{server=server,address=address} local socket = assert(uv.new_tcp()) assert(uv.tcp_connect(socket, "127.0.0.1", address.port, expect(function () assert(uv.read_start(socket, expect(function (err, data) p("client read", {err=err,data=data}) assert(not err, err) uv.close(socket) end))) local req = assert(uv.write(socket, "Hello", function (err) p("client onwrite", socket, err) assert(not err, err) end)) p{socket=socket,req=req} end))) end, "1.32.0") end) luv-1.36.0-0/tests/test-thread.lua000066400000000000000000000050021364617304100166370ustar00rootroot00000000000000return require('lib/tap')(function (test) test("test thread create", function(print, p, expect, uv) local delay = 100 uv.update_time() local before = uv.now() local thread = uv.new_thread(function(delay) local uv = require('luv') local t1 = uv.thread_self() uv.sleep(delay) local t2 = uv.thread_self() assert(t1:equal(t2)) assert(tostring(t1)==tostring(t2)) _G.print(' In', uv.thread_self()) end,delay) uv.thread_join(thread) uv.update_time() local elapsed = uv.now() - before p({ delay = delay, elapsed = elapsed }) assert(elapsed >= delay, "elapsed should be at least delay ") end) test("test thread create with arguments", function(print, p, expect, uv) uv.update_time() local before = uv.now() local args = {500, 'string', nil, false, 5, "helloworld"} local unpack = unpack or table.unpack uv.new_thread(function(num,s,null,bool,five,hw) assert(type(num) == "number") assert(type(s) == "string") assert(null == nil) assert(bool == false) assert(five == 5) assert(hw == 'helloworld') require('luv').sleep(100) end, unpack(args)):join() uv.update_time() local elapsed = uv.now() - before assert(elapsed >= 100, "elapsed should be at least delay ") end) test("test thread sleep msecs in main thread", function(print, p, expect, uv) local delay = 100 uv.update_time() local before = uv.now() print('Runing', uv.thread_self()) uv.sleep(delay) print('Runing', uv.thread_self()) uv.update_time() local elapsed = uv.now() - before p({ delay = delay, elapsed = elapsed }) assert(elapsed >= delay, "elapsed should be at least delay ") end) test("test thread create with options table", function(print, p, expect, uv) local delay = 100 uv.update_time() local before = uv.now() local args = {delay, 'string', nil, false, 5, "helloworld"} local unpack = unpack or table.unpack uv.new_thread({stack_size=0}, function(delay,s,null,bool,five,hw) assert(type(delay) == "number") assert(type(s) == "string") assert(null == nil) assert(bool == false) assert(five == 5) assert(hw == 'helloworld') require('luv').sleep(delay) end, unpack(args)):join() uv.update_time() local elapsed = uv.now() - before p({ delay = delay, elapsed = elapsed }) assert(elapsed >= 100, "elapsed should be at least delay ") end, "1.26.0") end) luv-1.36.0-0/tests/test-timer.lua000066400000000000000000000046201364617304100165150ustar00rootroot00000000000000return require('lib/tap')(function (test) -- This tests using timers for a simple timeout. -- It also tests the handle close callback and test("simple timeout", function (print, p, expect, uv) local timer = uv.new_timer() local function onclose() p("closed", timer) end local function ontimeout() p("timeout", timer) uv.close(timer, expect(onclose)) end uv.timer_start(timer, 10, 0, expect(ontimeout)) end) -- This is like the previous test, but using repeat. test("simple interval", function (print, p, expect, uv) local timer = uv.new_timer() local count = 3 local onclose = expect(function () p("closed", timer) end) local function oninterval() p("interval", timer) count = count - 1 if count == 0 then uv.close(timer, onclose) end end uv.timer_start(timer, 10, 10, oninterval) end) -- Test two concurrent timers -- There is a small race condition, but there are 100ms of wiggle room. -- 400ms is halfway between 100+200ms and 100+400ms test("timeout with interval", function (print, p, expect, uv) local a = uv.new_timer() local b = uv.new_timer() uv.timer_start(a, 400, 0, expect(function () p("timeout", a) uv.timer_stop(b) uv.close(a) uv.close(b) end)) uv.timer_start(b, 100, 200, expect(function () p("interval", b) end, 2)) end) -- This advanced test uses the rest of the uv_timer_t functions -- to create an interval that shrinks over time. test("shrinking interval", function (print, p, expect, uv) local timer = uv.new_timer() uv.timer_start(timer, 10, 0, expect(function () local r = uv.timer_get_repeat(timer) p("interval", timer, r) if r == 0 then uv.timer_set_repeat(timer, 8) uv.timer_again(timer) elseif r == 2 then uv.timer_stop(timer) uv.close(timer) else uv.timer_set_repeat(timer, r / 2) end end, 4)) end) test("shrinking interval using methods", function (print, p, expect, uv) local timer = uv.new_timer() timer:start(10, 0, expect(function () local r = timer:get_repeat() p("interval", timer, r) if r == 0 then timer:set_repeat(8) timer:again() elseif r == 2 then timer:stop() timer:close() else timer:set_repeat(r / 2) end end, 4)) end) end) luv-1.36.0-0/tests/test-udp.lua000066400000000000000000000131441364617304100161660ustar00rootroot00000000000000local TEST_PORT = 9123 return require('lib/tap')(function (test) test("basic udp server and client (ipv4)", function (print, p, expect, uv) local server = uv.new_udp() assert(uv.udp_bind(server, "0.0.0.0", TEST_PORT)) assert(uv.udp_recv_start(server, expect(function (err, data, addr, flags) p("server on recv", server, data, addr, flags) assert(not err, err) assert(data == "PING") uv.close(server, expect(function() p("server on close", server) end)) end))) p{server=server} local client = uv.new_udp() local req = assert(uv.udp_send(client, "PING", "127.0.0.1", TEST_PORT, expect(function (err) p("client on send", client, err) assert(not err, err) uv.close(client, expect(function() p("client on close", client) end)) end))) p{client=client,req=req} end) test("basic udp send from table", function (print, p, expect, uv) local sendData = {"P", "I", "NG"} local server = uv.new_udp() assert(uv.udp_bind(server, "0.0.0.0", TEST_PORT)) assert(uv.udp_recv_start(server, expect(function (err, data, addr, flags) p("server on recv", server, data, addr, flags) assert(not err, err) assert(data == table.concat(sendData)) uv.close(server, expect(function() p("server on close", server) end)) end))) p{server=server} local client = uv.new_udp() local req = assert(uv.udp_send(client, sendData, "127.0.0.1", TEST_PORT, expect(function (err) p("client on send", client, err) assert(not err, err) uv.close(client, expect(function() p("client on close", client) end)) end))) p{client=client,req=req} end) test("basic udp server and client (ipv6)", function (print, p, expect, uv) local server = uv.new_udp() local _, err = uv.udp_bind(server, "::1", TEST_PORT) if err then p("ipv6 unavailable", err) uv.close(server) return end assert(uv.udp_recv_start(server, expect(function (err, data, addr, flags) p("server on recv", server, data, addr, flags) assert(not err, err) assert(data == "PING") uv.close(server, expect(function() p("server on close", server) end)) end))) p{server=server} local client = uv.new_udp() local req = assert(uv.udp_send(client, "PING", "::1", TEST_PORT, expect(function (err) p("client on send", client, err) assert(not err, err) uv.close(client, expect(function() p("client on close", client) end)) end))) p{client=client,req=req} end) test("udp send args", function(print, p, expect, uv) local udp = uv.new_udp() local _, err = pcall(function() uv.udp_send(udp, "PING", 5, 5) end) print(assert(err)) _, err = pcall(function() uv.udp_send(udp, "PING", "host", "port") end) print(assert(err)) _, err = pcall(function() uv.udp_send(udp, "PING", "host", nil) end) print(assert(err)) _, err = pcall(function() uv.udp_send(udp, "PING", nil, 5) end) print(assert(err)) uv.close(udp) end, "1.27.0") test("udp connect", function(print, p, expect, uv) local server = uv.new_udp() local client = uv.new_udp() assert(uv.udp_bind(server, "0.0.0.0", TEST_PORT)) local numRecvs = 0 assert(uv.udp_recv_start(server, function (err, data, addr, flags) p("server on recv", server, data, addr, flags) assert(not err, err) -- nil data signifies nothing more to read if data ~= nil then assert(data == "PING", data) numRecvs = numRecvs + 1 if numRecvs == 4 then uv.close(server, expect(function() p("server on close", server) end)) uv.close(client, expect(function() p("client on close", client) end)) end end end)) p{server=server} assert(uv.udp_connect(client, "127.0.0.1", TEST_PORT)) local _, err = uv.udp_connect(client, "8.8.8.8", TEST_PORT) assert(err and err:sub(1,7) == "EISCONN", err) local addr = assert(uv.udp_getpeername(client)) p(addr) assert(addr.ip == "127.0.0.1") assert(addr.port == TEST_PORT) -- To send messages in connected UDP sockets addr must be NULL _, err = uv.udp_try_send(client, "PING", "127.0.0.1", TEST_PORT) assert(err and err:sub(1,7) == "EISCONN", err) local r = assert(uv.udp_try_send(client, "PING", nil, nil)) assert(r == 4) _, err = uv.udp_try_send(client, "PING", "8.8.8.8", TEST_PORT) assert(err and err:sub(1,7) == "EISCONN", err) assert(uv.udp_connect(client, nil, nil)) _, err = uv.udp_connect(client, nil, nil) assert(err and err:sub(1,8) == "ENOTCONN", err) _, err = uv.udp_getpeername(client) assert(err and err:sub(1,8) == "ENOTCONN", err) r = uv.udp_try_send(client, "PING", "127.0.0.1", TEST_PORT) assert(r == 4) _, err = uv.udp_try_send(client, "PING", nil, nil) assert(err and err:sub(1,12) == "EDESTADDRREQ", err) assert(uv.udp_connect(client, "127.0.0.1", TEST_PORT)) _, err = uv.udp_send(client, "PING", "127.0.0.1", TEST_PORT, function() error("this send should fail") end) assert(err and err:sub(1,7) == "EISCONN", err) assert(uv.udp_send(client, "PING", nil, nil, expect(function(err) assert(not err, err) uv.udp_connect(client, nil, nil) _, err = uv.udp_send(client, "PING", nil, nil, function() error("this send should fail") end) assert(err and err:sub(1,12) == "EDESTADDRREQ", err) uv.udp_send(client, "PING", "127.0.0.1", TEST_PORT, expect(function(err) assert(not err, err) end)) end))) end, "1.27.0") end) luv-1.36.0-0/tests/test-work.lua000066400000000000000000000045011364617304100163550ustar00rootroot00000000000000return require('lib/tap')(function (test) test("test threadpool", function(print,p,expect,_uv) p('Please be patient, the test cost a lots of time') local count = 1000 --for memleaks dected local step = 0 local ctx ctx = _uv.new_work( function(n,s) --work,in threadpool local uv = require('luv') local t = uv.thread_self() uv.sleep(10) return n, n*n, t, s end, function(n,r,id, s) assert(n*n==r) assert(#s==4096) if step < count then _uv.queue_work(ctx,n,s) step = step + 1 if (step % 100==0) then p(string.format('run %d%%', math.floor(step*100/count))) end else ctx = nil end end --after work, in loop thread ) local ls = string.rep('-',4096) _uv.queue_work(ctx,2,ls) _uv.queue_work(ctx,4,ls) _uv.queue_work(ctx,6,ls) _uv.queue_work(ctx,-2,ls) _uv.queue_work(ctx,-11,ls) _uv.queue_work(ctx,2,ls) _uv.queue_work(ctx,4,ls) _uv.queue_work(ctx,6,ls) _uv.queue_work(ctx,-2,ls) _uv.queue_work(ctx,-11,ls) _uv.queue_work(ctx,2,ls) _uv.queue_work(ctx,4,ls) _uv.queue_work(ctx,6,ls) _uv.queue_work(ctx,-2,ls) _uv.queue_work(ctx,-11,ls) _uv.queue_work(ctx,2,ls) _uv.queue_work(ctx,4,ls) _uv.queue_work(ctx,6,ls) _uv.queue_work(ctx,-2,ls) _uv.queue_work(ctx,-11,ls) end) test("test threadpool with async", function(print,p,expect,_uv) local ctx, async async = _uv.new_async(expect(function (a,b,c) p('in async notify callback') p(a,b,c) assert(a=='a') assert(b==true) assert(c==250) end)) ctx = _uv.new_work( function(n, s, a) --work,in threadpool local uv = require('luv') local t = tostring(uv.thread_self()) if a then assert(uv.async_send(a,'a',true,250)==0) end uv.sleep(10) return n, n*n, t, s end, function(n,r,id, s) --after work, in loop thread p(n, r, id, s) assert(n*n==r) if async then _uv.close(async) end print(id, 'finish', s) end ) _uv.queue_work(ctx,2,'hello',async) end) end)