<commit_before>local loader = function(loader, ...)

local socket = require("_cqueues.socket")
local cqueues = require("cqueues")
local errno = require("cqueues.errno")

local poll = cqueues.poll
local monotime = cqueues.monotime
local running = cqueues.running

local SOCK_STREAM = socket.SOCK_STREAM
local SOCK_DGRAM = socket.SOCK_DGRAM

local EAGAIN = errno.EAGAIN
local EPIPE = errno.EPIPE
local ETIMEDOUT = errno.ETIMEDOUT
local ENOTCONN = errno.ENOTCONN
local ENOTSOCK = errno.ENOTSOCK
local strerror = errno.strerror


--
-- H E L P E R  R O U T I N E S
--
-- ========================================================================

local function timed_poll(self, deadline)
	if deadline then
		local curtime = monotime()

		if deadline <= curtime then
			return false
		end

		poll(self, deadline - curtime)

		return true
	else
		poll(self)

		return true
	end
end -- timed_poll


--
-- E R R O R  M A N A G E M E N T
--
-- All errors in the I/O routines are first passed to a per-socket error
-- handler, which can choose to return or throw them.
--
-- The default error handler is not actually installed with any socket, as
-- that would create needless churn in the registry index on socket
-- instantiation. Instead we interpose socket.onerror and socket:onerror and
-- return our default handler if none was previously installed.
--
-- ========================================================================

-- default error handler
local function def_onerror(self, op, why, lvl)
	if why == EPIPE then
		return EPIPE
	elseif why == ETIMEDOUT then
		return ETIMEDOUT
	else
		local msg = string.format("socket.%s: %s", op, strerror(why))
		error(msg, lvl)
	end
end -- def_onerror


local _onerror = socket.onerror; socket.onerror = function(...)
	return _onerror(...) or def_onerror
end

local _onerror; _onerror = socket.interpose("onerror", function(...)
	return _onerror(...) or def_onerror
end)


--
-- On buffered I/O we need to preserve errors across calls, otherwise
-- unchecked transient errors might lead to unexpected behavior by
-- application code. This is particularly true regarding timeouts, and
-- especially so when mixed with iterators like socket:lines--doubly so when
-- reading MIME headers, which could terminate on ETIMEDOUT, EPIPE, or just
-- when reaching the end of the headers section.
--
-- Why not just always throw on such errors? One reason is that we partially
-- mimic Lua's file objects, which will return such errors. (And we might
-- change our semantics to fully mimic Lua in the future.)
--
-- Another reason is that it's very common to want to deal with timeouts
-- inline. For example, maybe you want to write a keep-alive message after a
-- read timeout. Timeouts are exceptional but not necessarily errors.
--
local preserve = {
	read = "r", lines = "r", fill = "r", unpack = "r",
	write = "w", flush = "w", pack = "w",

	-- these too for good measure, even though they're not buffered
	recvfd = "r", sendfd = "w",
}

-- drop EPIPE errors on input channel
local nopipe = {
	read = true, lines = true, fill = true, unpack = true, recvfd = true
}

local function oops(self, op, why, level)
	local onerror = self:onerror() or def_onerror

	if why == EPIPE and nopipe[op] then
		return -- EOF
	elseif preserve[op] then
		self:seterror(preserve[op], why)
	end

	-- NOTE: There's normally no need to increment on a tail-call
	-- (except when directly calling the error() routine), but we
	-- increment here so the callee has the correct stack level to pass
	-- to error() directly, without making adjustments for its own
	-- activation record.
	return onerror(self, op, why, (level or 2) + 1)
end -- oops


--
-- A P I  E X T E N S I O N S
--
-- The core sockets implementation in C will not yield on I/O, or throw
-- recoverable errors. These things are done in Lua code for simplicitly and
-- portability--Lua 5.1/LuaJIT doesn't support resumption of C routines.
--
-- ========================================================================


--<commit_msg>throw a more descriptive error message which includes peer address information, if possible<commit_after>local loader = function(loader, ...)

local socket = require("_cqueues.socket")
local cqueues = require("cqueues")
local errno = require("cqueues.errno")

local poll = cqueues.poll
local monotime = cqueues.monotime
local running = cqueues.running

local AF_INET = socket.AF_INET
local AF_INET6 = socket.AF_INET6
local AF_UNIX = socket.AF_UNIX
local SOCK_STREAM = socket.SOCK_STREAM
local SOCK_DGRAM = socket.SOCK_DGRAM

local EAGAIN = errno.EAGAIN
local EPIPE = errno.EPIPE
local ETIMEDOUT = errno.ETIMEDOUT
local ENOTCONN = errno.ENOTCONN
local ENOTSOCK = errno.ENOTSOCK
local strerror = errno.strerror

local format = string.format


--
-- H E L P E R  R O U T I N E S
--
-- ========================================================================

local function timed_poll(self, deadline)
	if deadline then
		local curtime = monotime()

		if deadline <= curtime then
			return false
		end

		poll(self, deadline - curtime)

		return true
	else
		poll(self)

		return true
	end
end -- timed_poll


local function logname(so)
	local af, addr, port = so:peername()

	if af == AF_INET or af == AF_INET6 then
		return format("%s.%s", addr, port)
	elseif af == AF_UNIX and #addr > 0 then
		return format("unix:%s", addr)
	end
end -- logname


--
-- E R R O R  M A N A G E M E N T
--
-- All errors in the I/O routines are first passed to a per-socket error
-- handler, which can choose to return or throw them.
--
-- The default error handler is not actually installed with any socket, as
-- that would create needless churn in the registry index on socket
-- instantiation. Instead we interpose socket.onerror and socket:onerror and
-- return our default handler if none was previously installed.
--
-- ========================================================================

-- default error handler
local function def_onerror(self, op, why, lvl)
	if why == EPIPE then
		return EPIPE
	elseif why == ETIMEDOUT then
		return ETIMEDOUT
	else
		local addr = logname(self)
		local msg

		if addr then
			msg = format("[%s]:%s: %s", addr, op, strerror(why))
		else
			msg = format("socket:%s: %s", op, strerror(why))
		end

		error(msg, lvl)
	end
end -- def_onerror


local _onerror = socket.onerror; socket.onerror = function(...)
	return _onerror(...) or def_onerror
end

local _onerror; _onerror = socket.interpose("onerror", function(...)
	return _onerror(...) or def_onerror
end)


--
-- On buffered I/O we need to preserve errors across calls, otherwise
-- unchecked transient errors might lead to unexpected behavior by
-- application code. This is particularly true regarding timeouts, and
-- especially so when mixed with iterators like socket:lines--doubly so when
-- reading MIME headers, which could terminate on ETIMEDOUT, EPIPE, or just
-- when reaching the end of the headers section.
--
-- Why not just always throw on such errors? One reason is that we partially
-- mimic Lua's file objects, which will return such errors. (And we might
-- change our semantics to fully mimic Lua in the future.)
--
-- Another reason is that it's very common to want to deal with timeouts
-- inline. For example, maybe you want to write a keep-alive message after a
-- read timeout. Timeouts are exceptional but not necessarily errors.
--
local preserve = {
	read = "r", lines = "r", fill = "r", unpack = "r",
	write = "w", flush = "w", pack = "w",

	-- these too for good measure, even though they're not buffered
	recvfd = "r", sendfd = "w",
}

-- drop EPIPE errors on input channel
local nopipe = {
	read = true, lines = true, fill = true, unpack = true, recvfd = true
}

local function oops(self, op, why, level)
	local onerror = self:onerror() or def_onerror

	if why == EPIPE and nopipe[op] then
		return -- EOF
	elseif preserve[op] then
		self:seterror(preserve[op], why)
	end

	-- NOTE: There's normally no need to increment on a tail-call
	-- (except when directly calling the error() routine), but we
	-- increment here so the callee has the correct stack level to pass
	-- to error() directly, without making adjustments for its own
	-- activation record.
	return onerror(self, op, why, (level or 2) + 1)
end -- oops


--
-- A P I  E X T E N S I O N S
--
-- The core sockets implementation in C will not yield on I/O, or throw
-- recoverable errors. These things are done in Lua code for simplicitly and
-- portability--Lua 5.1/LuaJIT doesn't support resumption of C routines.
--
-- ========================================================================

--
{'fraction_non_alphanumeric': 0.14240764479664375, 'fraction_numerical': 0.0013984384104416734, 'mean_word_length': 3.6189451022604953, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2704533', 'n_tokens_mistral': 2718, 'n_tokens_neox': 2515, 'n_words': 1107}