or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

addressing.mdcapabilities.mddatagram-sockets.mdexceptions.mdfile-descriptors.mdindex.mdnio-channels.mdrmi.mdsocket-pairs.mdunix-sockets.mdutilities.md

exceptions.mddocs/

0

# Exception Handling

1

2

Comprehensive exception hierarchy providing detailed error information for robust socket error handling and debugging in Unix Domain Socket operations.

3

4

## Capabilities

5

6

### AFException

7

8

Base exception class for all AF socket-related errors, extending IOException to integrate with standard Java I/O exception handling.

9

10

```java { .api }

11

/**

12

* Base exception class for AF socket operations

13

*/

14

public class AFException extends IOException {

15

16

/**

17

* Creates a new AFException with the specified message

18

* @param message The error message

19

*/

20

public AFException(String message);

21

22

/**

23

* Creates a new AFException with message and cause

24

* @param message The error message

25

* @param cause The underlying cause

26

*/

27

public AFException(String message, Throwable cause);

28

29

/**

30

* Creates a new AFException with the specified cause

31

* @param cause The underlying cause

32

*/

33

public AFException(Throwable cause);

34

35

// Error information

36

public String getMessage();

37

public Throwable getCause();

38

public String getLocalizedMessage();

39

40

// Stack trace information

41

public StackTraceElement[] getStackTrace();

42

public void printStackTrace();

43

public void printStackTrace(PrintStream s);

44

public void printStackTrace(PrintWriter s);

45

}

46

```

47

48

**Usage Examples:**

49

50

```java

51

import org.newsclub.net.unix.*;

52

53

try {

54

AFUNIXSocket socket = AFUNIXSocket.connectTo(AFUNIXSocketAddress.of("/nonexistent/path.sock"));

55

} catch (AFException e) {

56

System.err.println("AF Socket error: " + e.getMessage());

57

58

// Check for specific causes

59

Throwable cause = e.getCause();

60

if (cause instanceof FileNotFoundException) {

61

System.err.println("Socket file not found");

62

} else if (cause instanceof SecurityException) {

63

System.err.println("Permission denied");

64

}

65

66

// Log full stack trace for debugging

67

e.printStackTrace();

68

}

69

```

70

71

### Socket State Exceptions

72

73

Exceptions related to socket state and lifecycle management.

74

75

```java { .api }

76

/**

77

* Exception thrown when operating on closed sockets

78

*/

79

public class SocketClosedException extends SocketException {

80

public SocketClosedException();

81

public SocketClosedException(String msg);

82

public SocketClosedException(String msg, Throwable cause);

83

}

84

85

/**

86

* Exception thrown when socket address is unavailable

87

*/

88

public class AddressUnavailableSocketException extends SocketException {

89

public AddressUnavailableSocketException();

90

public AddressUnavailableSocketException(String msg);

91

public AddressUnavailableSocketException(String msg, Throwable cause);

92

}

93

94

/**

95

* Exception thrown when connection is refused

96

*/

97

public class ConnectionRefusedSocketException extends SocketException {

98

public ConnectionRefusedSocketException();

99

public ConnectionRefusedSocketException(String msg);

100

public ConnectionRefusedSocketException(String msg, Throwable cause);

101

}

102

```

103

104

**Usage Examples:**

105

106

```java

107

// Socket state validation

108

public void performSocketOperation(AFUNIXSocket socket) throws IOException {

109

try {

110

if (socket.isClosed()) {

111

throw new SocketClosedException("Socket is already closed");

112

}

113

114

// Perform operation

115

OutputStream os = socket.getOutputStream();

116

os.write("data".getBytes());

117

118

} catch (SocketClosedException e) {

119

System.err.println("Cannot operate on closed socket: " + e.getMessage());

120

throw e;

121

}

122

}

123

124

// Address availability check

125

public AFUNIXServerSocket createServer(File socketFile) throws IOException {

126

try {

127

AFUNIXSocketAddress address = AFUNIXSocketAddress.of(socketFile);

128

AFUNIXServerSocket server = AFUNIXServerSocket.newInstance();

129

server.bind(address);

130

return server;

131

132

} catch (AddressUnavailableSocketException e) {

133

System.err.println("Socket address unavailable: " + socketFile);

134

135

// Try to clean up and retry

136

if (socketFile.exists() && socketFile.delete()) {

137

System.out.println("Cleaned up stale socket file, retrying...");

138

return createServer(socketFile);

139

}

140

throw e;

141

}

142

}

143

144

// Connection handling

145

public void connectWithRetry(AFUNIXSocketAddress address, int maxRetries) throws IOException {

146

int attempts = 0;

147

148

while (attempts < maxRetries) {

149

try {

150

AFUNIXSocket socket = AFUNIXSocket.connectTo(address);

151

System.out.println("Connected successfully");

152

return;

153

154

} catch (ConnectionRefusedSocketException e) {

155

attempts++;

156

System.err.println("Connection refused, attempt " + attempts + "/" + maxRetries);

157

158

if (attempts >= maxRetries) {

159

throw new IOException("Failed to connect after " + maxRetries + " attempts", e);

160

}

161

162

try {

163

Thread.sleep(1000 * attempts); // Exponential backoff

164

} catch (InterruptedException ie) {

165

Thread.currentThread().interrupt();

166

throw new IOException("Connection interrupted", ie);

167

}

168

}

169

}

170

}

171

```

172

173

### Communication Exceptions

174

175

Exceptions related to data transmission and socket communication errors.

176

177

```java { .api }

178

/**

179

* Exception thrown when pipe is broken during communication

180

*/

181

public class BrokenPipeSocketException extends SocketException {

182

public BrokenPipeSocketException();

183

public BrokenPipeSocketException(String msg);

184

public BrokenPipeSocketException(String msg, Throwable cause);

185

}

186

187

/**

188

* Exception thrown when connection is reset by peer

189

*/

190

public class ConnectionResetSocketException extends SocketException {

191

public ConnectionResetSocketException();

192

public ConnectionResetSocketException(String msg);

193

public ConnectionResetSocketException(String msg, Throwable cause);

194

}

195

196

/**

197

* Exception thrown when socket times out

198

*/

199

public class SocketTimeoutException extends InterruptedIOException {

200

public SocketTimeoutException();

201

public SocketTimeoutException(String msg);

202

public SocketTimeoutException(String msg, Throwable cause);

203

}

204

```

205

206

**Usage Examples:**

207

208

```java

209

// Robust data transmission

210

public void sendDataWithErrorHandling(AFUNIXSocket socket, byte[] data) throws IOException {

211

try {

212

OutputStream os = socket.getOutputStream();

213

os.write(data);

214

os.flush();

215

216

} catch (BrokenPipeSocketException e) {

217

System.err.println("Broken pipe - peer closed connection: " + e.getMessage());

218

219

// Clean up resources

220

try {

221

socket.close();

222

} catch (IOException closeEx) {

223

e.addSuppressed(closeEx);

224

}

225

throw e;

226

227

} catch (ConnectionResetSocketException e) {

228

System.err.println("Connection reset by peer: " + e.getMessage());

229

230

// Log connection reset and clean up

231

logConnectionReset(socket, e);

232

throw e;

233

}

234

}

235

236

// Timeout handling

237

public String readWithTimeout(AFUNIXSocket socket, int timeoutMs) throws IOException {

238

try {

239

socket.setSoTimeout(timeoutMs);

240

241

InputStream is = socket.getInputStream();

242

byte[] buffer = new byte[1024];

243

int bytesRead = is.read(buffer);

244

245

if (bytesRead > 0) {

246

return new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);

247

}

248

return null;

249

250

} catch (SocketTimeoutException e) {

251

System.err.println("Read timeout after " + timeoutMs + "ms: " + e.getMessage());

252

253

// Decide whether to retry or fail

254

if (shouldRetryAfterTimeout(socket)) {

255

return readWithTimeout(socket, timeoutMs * 2); // Double timeout and retry

256

}

257

throw e;

258

259

} finally {

260

// Reset timeout

261

socket.setSoTimeout(0);

262

}

263

}

264

265

private boolean shouldRetryAfterTimeout(AFUNIXSocket socket) {

266

return socket.isConnected() && !socket.isClosed();

267

}

268

269

private void logConnectionReset(AFUNIXSocket socket, ConnectionResetSocketException e) {

270

try {

271

AFUNIXSocketAddress localAddr = (AFUNIXSocketAddress) socket.getLocalSocketAddress();

272

AFUNIXSocketAddress remoteAddr = (AFUNIXSocketAddress) socket.getRemoteSocketAddress();

273

274

System.err.println("Connection reset - Local: " + localAddr + ", Remote: " + remoteAddr);

275

} catch (Exception ex) {

276

System.err.println("Connection reset - Unable to get socket addresses");

277

}

278

}

279

```

280

281

### System and Platform Exceptions

282

283

Exceptions related to system-level errors and platform-specific issues.

284

285

```java { .api }

286

/**

287

* Exception thrown when device or resource is not found

288

*/

289

public class NoSuchDeviceSocketException extends SocketException {

290

public NoSuchDeviceSocketException();

291

public NoSuchDeviceSocketException(String msg);

292

public NoSuchDeviceSocketException(String msg, Throwable cause);

293

}

294

295

/**

296

* Exception thrown when operation is not supported

297

*/

298

public class OperationNotSupportedSocketException extends SocketException {

299

public OperationNotSupportedSocketException();

300

public OperationNotSupportedSocketException(String msg);

301

public OperationNotSupportedSocketException(String msg, Throwable cause);

302

}

303

304

/**

305

* Exception thrown when invalid argument is provided

306

*/

307

public class InvalidArgumentSocketException extends SocketException {

308

public InvalidArgumentSocketException();

309

public InvalidArgumentSocketException(String msg);

310

public InvalidArgumentSocketException(String msg, Throwable cause);

311

}

312

```

313

314

**Usage Examples:**

315

316

```java

317

// Platform capability checking

318

public void performPlatformSpecificOperation(AFUNIXSocket socket) throws IOException {

319

try {

320

// Attempt platform-specific operation (e.g., peer credentials)

321

PeerCredentials credentials = socket.getPeerCredentials();

322

System.out.println("Peer PID: " + credentials.getPid());

323

324

} catch (OperationNotSupportedSocketException e) {

325

System.err.println("Peer credentials not supported on this platform: " + e.getMessage());

326

327

// Fall back to alternative approach

328

performAlternativeAuthentication(socket);

329

330

} catch (NoSuchDeviceSocketException e) {

331

System.err.println("Required device not available: " + e.getMessage());

332

throw new IOException("Platform requirements not met", e);

333

}

334

}

335

336

// Argument validation

337

public void configureSocket(AFUNIXSocket socket, Map<String, Object> options) throws IOException {

338

try {

339

for (Map.Entry<String, Object> option : options.entrySet()) {

340

applySocketOption(socket, option.getKey(), option.getValue());

341

}

342

343

} catch (InvalidArgumentSocketException e) {

344

System.err.println("Invalid socket configuration: " + e.getMessage());

345

346

// Log configuration details for debugging

347

System.err.println("Configuration options: " + options);

348

throw new IllegalArgumentException("Socket configuration failed", e);

349

}

350

}

351

352

private void applySocketOption(AFUNIXSocket socket, String optionName, Object value) throws IOException {

353

switch (optionName.toLowerCase()) {

354

case "timeout":

355

if (!(value instanceof Integer)) {

356

throw new InvalidArgumentSocketException("Timeout must be an integer");

357

}

358

socket.setSoTimeout((Integer) value);

359

break;

360

361

case "keepalive":

362

if (!(value instanceof Boolean)) {

363

throw new InvalidArgumentSocketException("KeepAlive must be a boolean");

364

}

365

socket.setKeepAlive((Boolean) value);

366

break;

367

368

default:

369

throw new InvalidArgumentSocketException("Unknown socket option: " + optionName);

370

}

371

}

372

373

private void performAlternativeAuthentication(AFUNIXSocket socket) {

374

// Alternative authentication mechanism

375

System.out.println("Using alternative authentication method");

376

}

377

```

378

379

## Exception Handling Patterns

380

381

### Comprehensive Error Handling

382

383

```java

384

// Complete error handling pattern for socket operations

385

public class RobustSocketClient {

386

private static final int MAX_RETRIES = 3;

387

private static final int RETRY_DELAY_MS = 1000;

388

389

public void performRobustOperation(File socketFile, byte[] data) throws IOException {

390

AFUNIXSocketAddress address = AFUNIXSocketAddress.of(socketFile);

391

IOException lastException = null;

392

393

for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {

394

try {

395

performSingleOperation(address, data);

396

return; // Success

397

398

} catch (AddressUnavailableSocketException e) {

399

System.err.println("Attempt " + attempt + ": Address unavailable - " + e.getMessage());

400

lastException = e;

401

402

if (attempt == MAX_RETRIES) {

403

throw new IOException("Socket server appears to be down", e);

404

}

405

406

} catch (ConnectionRefusedSocketException e) {

407

System.err.println("Attempt " + attempt + ": Connection refused - " + e.getMessage());

408

lastException = e;

409

410

if (attempt == MAX_RETRIES) {

411

throw new IOException("Server not accepting connections", e);

412

}

413

414

} catch (BrokenPipeSocketException | ConnectionResetSocketException e) {

415

System.err.println("Attempt " + attempt + ": Connection lost - " + e.getMessage());

416

lastException = e;

417

418

// Don't retry on connection loss

419

throw new IOException("Connection lost during operation", e);

420

421

} catch (SocketTimeoutException e) {

422

System.err.println("Attempt " + attempt + ": Operation timed out - " + e.getMessage());

423

lastException = e;

424

425

if (attempt == MAX_RETRIES) {

426

throw new IOException("Operation timed out after " + MAX_RETRIES + " attempts", e);

427

}

428

429

} catch (OperationNotSupportedSocketException e) {

430

// Don't retry unsupported operations

431

throw new IOException("Operation not supported on this platform", e);

432

433

} catch (AFException e) {

434

System.err.println("Attempt " + attempt + ": AF socket error - " + e.getMessage());

435

lastException = e;

436

437

if (attempt == MAX_RETRIES) {

438

throw new IOException("Socket operation failed", e);

439

}

440

}

441

442

if (attempt < MAX_RETRIES) {

443

try {

444

Thread.sleep(RETRY_DELAY_MS * attempt); // Progressive delay

445

} catch (InterruptedException ie) {

446

Thread.currentThread().interrupt();

447

throw new IOException("Operation interrupted", ie);

448

}

449

}

450

}

451

452

throw new IOException("All retry attempts failed", lastException);

453

}

454

455

private void performSingleOperation(AFUNIXSocketAddress address, byte[] data) throws IOException {

456

try (AFUNIXSocket socket = AFUNIXSocket.connectTo(address)) {

457

socket.setSoTimeout(5000); // 5 second timeout

458

459

// Send data

460

OutputStream os = socket.getOutputStream();

461

os.write(data);

462

os.flush();

463

464

// Read response

465

InputStream is = socket.getInputStream();

466

byte[] buffer = new byte[1024];

467

int bytesRead = is.read(buffer);

468

469

if (bytesRead > 0) {

470

String response = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);

471

System.out.println("Received: " + response);

472

}

473

}

474

}

475

}

476

```

477

478

### Exception Classification and Recovery

479

480

```java

481

// Exception classification for different recovery strategies

482

public class ExceptionHandler {

483

484

public enum ErrorSeverity {

485

RECOVERABLE, // Can retry

486

TRANSIENT, // May recover after delay

487

PERMANENT, // Don't retry

488

FATAL // Should terminate

489

}

490

491

public static ErrorSeverity classifyException(Exception e) {

492

if (e instanceof SocketClosedException) {

493

return ErrorSeverity.PERMANENT;

494

} else if (e instanceof AddressUnavailableSocketException) {

495

return ErrorSeverity.TRANSIENT;

496

} else if (e instanceof ConnectionRefusedSocketException) {

497

return ErrorSeverity.TRANSIENT;

498

} else if (e instanceof BrokenPipeSocketException) {

499

return ErrorSeverity.PERMANENT;

500

} else if (e instanceof ConnectionResetSocketException) {

501

return ErrorSeverity.PERMANENT;

502

} else if (e instanceof SocketTimeoutException) {

503

return ErrorSeverity.RECOVERABLE;

504

} else if (e instanceof OperationNotSupportedSocketException) {

505

return ErrorSeverity.FATAL;

506

} else if (e instanceof InvalidArgumentSocketException) {

507

return ErrorSeverity.FATAL;

508

} else if (e instanceof AFException) {

509

return ErrorSeverity.TRANSIENT;

510

}

511

return ErrorSeverity.PERMANENT;

512

}

513

514

public static boolean shouldRetry(Exception e, int attemptCount, int maxAttempts) {

515

if (attemptCount >= maxAttempts) {

516

return false;

517

}

518

519

ErrorSeverity severity = classifyException(e);

520

return severity == ErrorSeverity.RECOVERABLE || severity == ErrorSeverity.TRANSIENT;

521

}

522

523

public static long getRetryDelay(Exception e, int attemptCount) {

524

ErrorSeverity severity = classifyException(e);

525

526

switch (severity) {

527

case RECOVERABLE:

528

return Math.min(1000L * (1L << attemptCount), 30000L); // Exponential backoff, max 30s

529

case TRANSIENT:

530

return Math.min(2000L * attemptCount, 10000L); // Linear backoff, max 10s

531

default:

532

return 0L;

533

}

534

}

535

}

536

```

537

538

### Logging and Monitoring

539

540

```java

541

// Exception logging for monitoring and debugging

542

public class SocketExceptionLogger {

543

private static final Logger logger = LoggerFactory.getLogger(SocketExceptionLogger.class);

544

545

public static void logException(Exception e, AFUNIXSocket socket, String operation) {

546

Map<String, Object> context = new HashMap<>();

547

context.put("operation", operation);

548

context.put("exception_type", e.getClass().getSimpleName());

549

context.put("exception_message", e.getMessage());

550

551

try {

552

if (socket != null) {

553

context.put("socket_closed", socket.isClosed());

554

context.put("socket_connected", socket.isConnected());

555

context.put("socket_bound", socket.isBound());

556

557

if (socket.getLocalSocketAddress() != null) {

558

context.put("local_address", socket.getLocalSocketAddress().toString());

559

}

560

if (socket.getRemoteSocketAddress() != null) {

561

context.put("remote_address", socket.getRemoteSocketAddress().toString());

562

}

563

}

564

} catch (Exception ex) {

565

context.put("socket_info_error", ex.getMessage());

566

}

567

568

ExceptionHandler.ErrorSeverity severity = ExceptionHandler.classifyException(e);

569

context.put("error_severity", severity.toString());

570

571

// Log based on severity

572

switch (severity) {

573

case FATAL:

574

logger.error("Fatal socket error: {}", context, e);

575

break;

576

case PERMANENT:

577

logger.warn("Permanent socket error: {}", context, e);

578

break;

579

case TRANSIENT:

580

logger.info("Transient socket error: {}", context);

581

break;

582

case RECOVERABLE:

583

logger.debug("Recoverable socket error: {}", context);

584

break;

585

}

586

}

587

}

588

```