Skip to content

socket.read() freezes when 4096 or multiple of 4096 bytes in socket for readout #181

Description

@wojruc

Tested on Linux and MacOS and manifests on both.

Below is the reproduction pattern. Just copy/paste to SocketsTests.swift and run tests.

`

    func testReadX4096BytesIssue() {
	
	var data = Data()
	
	do {
		
		// Launch the server helper...
		launchServerHelper(family: .unix)
		
		// Need to wait for the server to come up...
		#if os(Linux)
			_ = Glibc.sleep(2)
		#else
			_ = Darwin.sleep(2)
		#endif
		
		// Create the signature...
		let signature = try Socket.Signature(socketType: .stream, proto: .unix, path: path)!
		
		// Create the socket...
		let socket = try createHelper(family: .unix)
		
		// Defer cleanup...
		defer {
			// Close the socket...
			socket.close()
			XCTAssertFalse(socket.isActive)
		}
		
		// Connect to the server helper...
		try socket.connect(using: signature)
		if !socket.isConnected {
			
			fatalError("Failed to connect to the server...")
		}
		
		print("\nConnected to path: \(path)")
		print("\tSocket signature: \(socket.signature!.description)\n")
		
		_ = try readAndPrint(socket: socket, data: &data)
		
		for count in [4095, 4097, 4096]
		{
			let hello = String(repeating: "a", count: count)
			let bytesWritten = try socket.write(from: hello)
			
			print("Wrote '\(bytesWritten)' bytes to socket...")
			
			let response = try readAndPrint(socket: socket, data: &data)

			XCTAssertNotNil(response)
			XCTAssertEqual(response!, "Server response: \n\(hello)\n")
		}			
		try socket.write(from: "QUIT")
		
		print("Sent quit to server...")
		
		// Need to wait for the server to go down before continuing...
		#if os(Linux)
			_ = Glibc.sleep(1)
		#else
			_ = Darwin.sleep(1)
		#endif
		
	} catch let error {
		
		// See if it's a socket error or something else...
		guard let socketError = error as? Socket.Error else {
			
			print("Unexpected error...")
			XCTFail()
			return
		}
		
		print("testReadWriteUnix Error reported: \(socketError.description)")
		XCTFail()
	}
}

static var allTests = [
	("testDefaultCreate", testDefaultCreate),
	("testCreateIPV6", testCreateIPV6),
	("testCreateUnix", testCreateUnix),
	("testCreateUDP", testCreateUDP),
	("testListen", testListen),
	("testListenPort0", testListenPort0),
	("testListenUnix", testListenUnix),
	("testListenUDP", testListenUDP),
	("testListenPort0UDP", testListenPort0UDP),
	("testConnect", testConnect),
	("testConnectTo", testConnectTo),
	("testConnectToWithTimeout", testConnectToWithTimeout),
	("testConnectToPath", testConnectToPath),
	("testConnectPort0", testConnectPort0),
	("testHostnameAndPort", testHostnameAndPort),
	("testBlocking", testBlocking),
	("testSetReadTimeout", testSetReadTimeout),
	("testSetWriteTimeout", testSetWriteTimeout),
	("testIsReadableWritableFail", testIsReadableWritableFail),
	("testIsReadableWritable", testIsReadableWritable),
	("testFDSetBitFields", testFDSetBitFields),
	("testDomainSocketPath", testDomainSocketPath),
	("testReadWrite", testReadWrite),
	("testTruncateTCP", testTruncateTCP),
	("testReadWriteUDP", testReadWriteUDP),
	("testReadWriteUnix", testReadWriteUnix),
	("testReadWriteUnix", testReadX4096BytesIssue),
]

}
`

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions