Skip to content
This repository has been archived by the owner on Sep 1, 2023. It is now read-only.

Commit

Permalink
1.0.11: Fixed deadlock when child process reads from stdin
Browse files Browse the repository at this point in the history
- Fixed a deadlock that can occur when the child process tries to read
  from the standard input

- The deadlock occurs because jobson provides no standard input to child
  processes, but keeps the standard input open. This causes child processes
  to deadlock indefinitely when 'read'ing from stdin

- This fix makes jobson 'close' the standard input of any child process
  at launch time. If any child process attempts to read from the standard
  input they'll read 0 bytes then stop

- See #67 for more info

- Thanks to @Russel88 for finding this bug!
  • Loading branch information
adamkewley committed Dec 30, 2020
2 parents 8e2d20d + 77e903a commit ced8e1c
Show file tree
Hide file tree
Showing 14 changed files with 62 additions and 31 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ addons:
- python3
- python3-pip
- python3-setuptools
- python3-venv
- nodejs
- docker
before_install:
- gem install fpm --version 1.10.0
- pip3 install --user --upgrade pip virtualenv
- virtualenv -p python3 venv
- pip3 install --user --upgrade pip
- python3 -m venv venv/
- source venv/bin/activate
- pip3 install -r jobson-docs/requirements.txt
script: mvn package
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ Requires java (8+):
```bash
# install and add to PATH
wget https://github.com/adamkewley/jobson/releases/download/1.0.10/jobson-nix-1.0.10.tar.gz
tar xvf jobson-nix-1.0.10.tar.gz
export PATH=$PATH:jobson-nix-1.0.10/bin
wget https://github.com/adamkewley/jobson/releases/download/1.0.11/jobson-nix-1.0.11.tar.gz
tar xvf jobson-nix-1.0.11.tar.gz
export PATH=$PATH:jobson-nix-1.0.11/bin

# create demo workspace
jobson new --demo
Expand Down
4 changes: 2 additions & 2 deletions jobson-deb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</parent>

<artifactId>jobson-deb</artifactId>
Expand All @@ -17,7 +17,7 @@
<dependency>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-nix</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<type>tar.gz</type>
</dependency>
</dependencies>
Expand Down
4 changes: 2 additions & 2 deletions jobson-docker/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</parent>

<artifactId>jobson-docker</artifactId>
Expand All @@ -17,7 +17,7 @@
<dependency>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-deb</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<type>deb</type>
</dependency>
</dependencies>
Expand Down
4 changes: 2 additions & 2 deletions jobson-docs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<parent>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</parent>

<artifactId>jobson-docs</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<packaging>pom</packaging>

<dependencies>
Expand Down
8 changes: 4 additions & 4 deletions jobson-nix/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</parent>

<artifactId>jobson-nix</artifactId>
Expand All @@ -17,18 +17,18 @@
<dependency>
<groupId>com.github.jobson</groupId>
<artifactId>jobson</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</dependency>
<dependency>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-docs</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<type>tar.gz</type>
</dependency>
<dependency>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-ui</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<type>tar.gz</type>
</dependency>
</dependencies>
Expand Down
4 changes: 2 additions & 2 deletions jobson-swagger-ui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<parent>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</parent>

<artifactId>jobson-swagger-ui</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<packaging>pom</packaging>

<dependencies>
Expand Down
6 changes: 3 additions & 3 deletions jobson-swagger/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@
<parent>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</parent>

<artifactId>jobson-swagger</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<packaging>pom</packaging>

<dependencies>
<dependency>
<groupId>com.github.jobson</groupId>
<artifactId>jobson</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml</groupId>
Expand Down
4 changes: 2 additions & 2 deletions jobson-ui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<parent>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</parent>

<artifactId>jobson-ui</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<packaging>pom</packaging>

<build>
Expand Down
4 changes: 2 additions & 2 deletions jobson/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<parent>
<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
</parent>

<artifactId>jobson</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<packaging>jar</packaging>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ public CancelablePromise<JobExecutionResult> execute(PersistedJob req, JobEventL

final Process runningProcess = processBuilder.start();

// close process's stdin stream. If this isn't done, the
// child process will block if it tries to read from stdin
// (because it's connected to jobson's stdin, which isn't
// being used)
//
// see https://github.com/adamkewley/jobson/issues/67 for
// a breakdown of the kinds of problems this can create
runningProcess.getOutputStream().close();

log.info(req.getId() + ": launched: " + String.join(" ", argList));

final SimpleCancelablePromise<JobExecutionResult> ret = new SimpleCancelablePromise<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ public void testExecutePromiseResolvesWithFatalErrorForFailingCommand() throws T
@Test
public void testExecutePromiseResolvesWithAbortedIfPromiseIsCancelled() throws Throwable {
final JobExecutor jobExecutor = getInstance();
final PersistedJob req =
standardRequestWithCommand("cat"); // Long-running, because it blocks on an STDIN read.
final PersistedJob req = standardRequestWithCommand("sleep", "100");
final CancelablePromise<JobExecutionResult> ret =
jobExecutor.execute(req, createNullListeners());

Expand All @@ -195,6 +194,28 @@ public void testExecutePromiseResolvesWithAbortedIfPromiseIsCancelled() throws T
() -> ret.cancel(true));
}

@Test
public void testExecutePromiseResolvesCompletedIfApplicationReadsFromStdin() throws Throwable {
// jobson should close `stdin`, so that any application
// attempting to read from stdin reads nothing (rather than
// deadlocking indefinitely on content Jobson will never
// write)
//
// see: https://github.com/adamkewley/jobson/issues/67
//
// (abstract): user ran an application that reads from stdin
// in certain circumstances and Jobson was deadlocking on that
final JobExecutor jobExecutor = getInstance();
final PersistedJob req = standardRequestWithCommand("cat"); // reads from stdin
final CancelablePromise<JobExecutionResult> ret =
jobExecutor.execute(req, createNullListeners());

promiseAssert(
ret,
result -> assertThat(result.getFinalStatus()).isEqualTo(JobStatus.FINISHED),
() -> ret.cancel(true));
}

@Test
public void testExecutePromiseResolvesWithTheOutputsWrittenByTheApplication() throws Throwable {
final JobExecutor jobExecutor = getInstance();
Expand Down
4 changes: 2 additions & 2 deletions jobson/src/test/resources/fixtures/systemtests/jobspecs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
expectedInputs: []

execution:
application: cat
arguments: []
application: sleep
arguments: ['100']

- id: fourth-spec
name: Spec that creates an output
Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.github.jobson</groupId>
<artifactId>jobson-project</artifactId>
<version>1.0.10</version>
<version>1.0.11</version>
<packaging>pom</packaging>

<name>jobson project</name>
Expand Down Expand Up @@ -48,8 +48,8 @@
</developers>

<properties>
<version.jobsonswagger>1.0.10</version.jobsonswagger>
<version.jobsonswaggerui>1.0.10</version.jobsonswaggerui>
<version.jobsonswagger>1.0.11</version.jobsonswagger>
<version.jobsonswaggerui>1.0.11</version.jobsonswaggerui>

<dropwizard.version>2.0.10</dropwizard.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down

0 comments on commit ced8e1c

Please sign in to comment.