Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wojruc opened this issue Dec 6, 2019 · 1 comment

Comments

@wojruc
Copy link

wojruc commented Dec 6, 2019

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),
]

}
`

@Pegolon
Copy link

Pegolon commented Sep 15, 2020

Just discovered this issue, too. It is a rather annoying blocker. My solution was to increase the readBufferSize to 5 MB, since none of my packets will be bigger and I am using Unix domain sockets, but it would be much better to use a timeout and let not block the application.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants