Bug Description
The start() method uses .sync() on the bind operation, which blocks indefinitely if the bind fails or hangs. This can cause the application startup to freeze.
Location
jplatform-rest-api-netty/src/main/java/org/flossware/jplatform/rest/netty/NettyApiServer.java:124
Problematic Code
ChannelFuture future = bootstrap.bind(config.getHost(), config.getPort()).sync();
serverChannel = future.channel();
running = true;
Impact
- Indefinite hang: If bind operation stalls, application startup freezes
- No timeout: No way to detect and recover from hang
- Thread blocked: Startup thread blocked indefinitely
- No feedback: User doesn't know why startup is stuck
- Resource leak: EventLoopGroups created but server not running
Example
// Port already in use or firewall blocking
NettyApiServer server = new NettyApiServer(config);
server.start();
// bind() operation queued but never completes
// sync() blocks forever
// Application appears to hang during startup
// No exception, no timeout, no log message
// EventLoopGroups consuming resources
Proposed Fix
@Override
public void start() throws ServerStartupException {
if (running) {
return;
}
try {
bossGroup = new NioEventLoopGroup(config.getBossThreads());
workerGroup = config.getWorkerThreads() > 0
? new NioEventLoopGroup(config.getWorkerThreads())
: new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(config.getMaxContentLength()));
pipeline.addLast(new HttpRequestHandler(routes));
}
})
.option(ChannelOption.SO_BACKLOG, config.getBacklog())
.childOption(ChannelOption.SO_KEEPALIVE, config.isKeepAlive());
// Bind with timeout
ChannelFuture bindFuture = bootstrap.bind(config.getHost(), config.getPort());
// Wait for bind to complete with timeout
if (!bindFuture.await(30, TimeUnit.SECONDS)) {
// Timeout waiting for bind
throw new ServerStartupException(
"Timeout waiting for server to bind to " + config.getHost() + ":" + config.getPort(),
config.getPort(),
null
);
}
// Check if bind was successful
if (!bindFuture.isSuccess()) {
throw new ServerStartupException(
"Failed to bind server to " + config.getHost() + ":" + config.getPort(),
config.getPort(),
bindFuture.cause()
);
}
serverChannel = bindFuture.channel();
running = true;
logger.info("Netty API server started on {}:{}", config.getHost(), config.getPort());
} catch (ServerStartupException e) {
// Cleanup resources on failure
cleanupResources();
throw e;
} catch (Exception e) {
cleanupResources();
logger.error("Failed to start Netty API server", e);
throw new ServerStartupException("Failed to start server", config.getPort(), e);
}
}
private void cleanupResources() {
if (workerGroup != null) {
workerGroup.shutdownGracefully();
}
if (bossGroup != null) {
bossGroup.shutdownGracefully();
}
}
Bug Description
The
start()method uses.sync()on the bind operation, which blocks indefinitely if the bind fails or hangs. This can cause the application startup to freeze.Location
jplatform-rest-api-netty/src/main/java/org/flossware/jplatform/rest/netty/NettyApiServer.java:124Problematic Code
Impact
Example
Proposed Fix