Skip to content

Commit 4c95637

Browse files
authored
Merge pull request #160 from bugsnag/release-v3.6.2
Release v3.6.2
2 parents 2720baa + 76e6ce6 commit 4c95637

File tree

9 files changed

+87
-18
lines changed

9 files changed

+87
-18
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# Changelog
22

3-
## 3.6.1 (2019-15-08)
3+
## 3.6.2 (2020-11-10)
4+
5+
* Fix JVM hang when System.exit or bugsnag.close is not called
6+
[#157](https://github.com/bugsnag/bugsnag-java/pull/157)
7+
8+
## 3.6.1 (2019-08-15)
49

510
* Prevent potential ConcurrentModificationException when adding callback
611
[#149](https://github.com/bugsnag/bugsnag-java/pull/149)

CONTRIBUTING.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,23 @@ Thanks!
1616

1717
## Testing
1818

19-
Runs tests and checkstyle.
19+
### Unit tests and checkstyle
2020

2121
```
2222
./gradlew check
2323
```
2424

25+
### End-to-end tests
26+
27+
These tests are implemented with our notifier testing tool [Maze runner](https://github.com/bugsnag/maze-runner).
28+
29+
End to end tests are written in cucumber-style `.feature` files, and need Ruby-backed "steps" in order to know what to run. The tests are located in the top level [`features`](/features/) directory.
30+
31+
```
32+
bundle install
33+
bundle exec bugsnag-maze-runner
34+
```
35+
2536
## Installing/testing against a local maven repository
2637

2738
Sometimes its helpful to build and install the bugsnag-java libraries into a

bugsnag/src/main/java/com/bugsnag/Bugsnag.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.bugsnag.callbacks.Callback;
44
import com.bugsnag.delivery.Delivery;
55
import com.bugsnag.delivery.HttpDelivery;
6+
import com.bugsnag.util.DaemonThreadFactory;
67

78
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
@@ -46,7 +47,7 @@ public Thread newThread(Runnable runnable) {
4647

4748
private ScheduledThreadPoolExecutor sessionExecutorService =
4849
new ScheduledThreadPoolExecutor(CORE_POOL_SIZE,
49-
Executors.defaultThreadFactory(),
50+
new DaemonThreadFactory(),
5051
new RejectedExecutionHandler() {
5152
@Override
5253
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {

bugsnag/src/main/java/com/bugsnag/Notifier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
class Notifier {
66

77
private static final String NOTIFIER_NAME = "Bugsnag Java";
8-
private static final String NOTIFIER_VERSION = "3.6.1";
8+
private static final String NOTIFIER_VERSION = "3.6.2";
99
private static final String NOTIFIER_URL = "https://github.com/bugsnag/bugsnag-java";
1010

1111
private String notifierName = NOTIFIER_NAME;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.bugsnag.util;
2+
3+
import java.util.concurrent.Executors;
4+
import java.util.concurrent.ThreadFactory;
5+
6+
/**
7+
* Wraps {@link Executors#defaultThreadFactory()} to return daemon threads
8+
* This is to prevent applications from hanging waiting for the sessions scheduled task
9+
* because daemon threads will be terminated on application shutdown
10+
*/
11+
public class DaemonThreadFactory implements ThreadFactory {
12+
private final ThreadFactory defaultThreadFactory;
13+
14+
/**
15+
* Constructor
16+
*/
17+
public DaemonThreadFactory() {
18+
defaultThreadFactory = Executors.defaultThreadFactory();
19+
}
20+
21+
@Override
22+
public Thread newThread(Runnable runner) {
23+
Thread daemonThread = defaultThreadFactory.newThread(runner);
24+
daemonThread.setName("bugsnag-daemon-" + daemonThread.getId());
25+
26+
// Set the threads to daemon to allow the app to shutdown properly
27+
if (!daemonThread.isDaemon()) {
28+
daemonThread.setDaemon(true);
29+
}
30+
return daemonThread;
31+
}
32+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.bugsnag;
2+
3+
import static org.junit.Assert.assertTrue;
4+
5+
import com.bugsnag.util.DaemonThreadFactory;
6+
7+
import org.junit.Before;
8+
import org.junit.Test;
9+
10+
11+
/**
12+
* Tests for the Daemon thread factory internal logic
13+
*/
14+
public class DaemonThreadFactoryTest {
15+
16+
private DaemonThreadFactory daemonThreadFactory;
17+
18+
/**
19+
* Create the daemonThreadFactory before the tests
20+
*/
21+
@Before
22+
public void createFactory() {
23+
daemonThreadFactory = new DaemonThreadFactory();
24+
}
25+
26+
@Test
27+
public void testDaemonThreadFactory() {
28+
Thread testThread = daemonThreadFactory.newThread(null);
29+
30+
// Check that the thread is as expected
31+
assertTrue(testThread.isDaemon());
32+
}
33+
}

examples/simple/src/main/java/com/bugsnag/example/simple/ExampleApp.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,5 @@ public void run() {
7474

7575
// Wait for unhandled exception thread to finish before exiting
7676
thread.join();
77-
78-
System.exit(0);
7977
}
8078
}

features/fixtures/mazerunner/src/main/java/com/bugsnag/mazerunner/TestCaseRunner.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import org.slf4j.LoggerFactory;
77
import org.springframework.beans.BeansException;
88
import org.springframework.boot.CommandLineRunner;
9-
import org.springframework.boot.ExitCodeGenerator;
10-
import org.springframework.boot.SpringApplication;
119
import org.springframework.context.ApplicationContext;
1210
import org.springframework.context.ApplicationContextAware;
1311
import org.springframework.stereotype.Component;
@@ -41,15 +39,6 @@ public void run(String... args) {
4139
} else {
4240
LOGGER.error("No test case found for " + System.getenv("EVENT_TYPE"));
4341
}
44-
45-
// Exit the application
46-
LOGGER.info("Exiting spring");
47-
System.exit(SpringApplication.exit(ctx, (ExitCodeGenerator) new ExitCodeGenerator() {
48-
@Override
49-
public int getExitCode() {
50-
return 0;
51-
}
52-
}));
5342
}
5443

5544
private void setupBugsnag() {

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version=3.6.1
1+
version=3.6.2
22
group=com.bugsnag
33

44
# Default properties

0 commit comments

Comments
 (0)