Skip to content

Commit

Permalink
fix(core): prevent post install failures when socket path too long (n…
Browse files Browse the repository at this point in the history
…rwl#27366)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
We communicate with sockets during graph construction. Its possible for
the assigned path to be too long and this can cause issues. The issues
present as a strange error with no helpful information.

## Expected Behavior
There is a helpful error message, and post-install is not interrupted

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes nrwl#27040
  • Loading branch information
AgentEnder authored Aug 10, 2024
1 parent a4169a1 commit abfb25d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/shared/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ The following environment variables are ones that you can set to change the beha
| NX_LOAD_DOT_ENV_FILES | boolean | If set to 'false', Nx will not load any environment files (e.g. `.local.env`, `.env.local`) |
| NX_NATIVE_FILE_CACHE_DIRECTORY | string | The cache for native `.node` files is stored under a global temp directory by default. Set this variable to use a different directory. This is interpreted as an absolute path. |
| NX_PLUGIN_NO_TIMEOUTS | boolean | If set to `true`, plugin operations will not timeout |
| NX_SOCKET_DIRECTORY | string | Sets the directory that Nx will use when creating sockets to communicate with child processes. May be needed if the derived socket path is too long. |

Nx will set the following environment variables so they can be accessible within the process even outside of executors and generators.

Expand Down
10 changes: 10 additions & 0 deletions packages/nx/bin/post-install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,13 @@ function isMainNxPackage() {
const thisNxPath = require.resolve('nx');
return mainNxPath === thisNxPath;
}

process.on('uncaughtException', (e) => {
logger.verbose(e);
process.exit(0);
});

process.on('unhandledRejection', (e) => {
logger.verbose(e);
process.exit(0);
});
37 changes: 30 additions & 7 deletions packages/nx/src/daemon/socket-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { unlinkSync } from 'fs';
import { platform } from 'os';
import { platform, tmpdir } from 'os';
import { join, resolve } from 'path';
import { getDaemonSocketDir, getSocketDir } from './tmp-dir';
import { createSerializableError } from '../utils/serializable-error';
Expand All @@ -12,21 +12,44 @@ export const isWindows = platform() === 'win32';
* See https://nodejs.org/dist/latest-v14.x/docs/api/net.html#net_identifying_paths_for_ipc_connections for a full breakdown
* of OS differences between Unix domain sockets and named pipes.
*/
export const getFullOsSocketPath = () =>
isWindows
? '\\\\.\\pipe\\nx\\' + resolve(getDaemonSocketDir())
: resolve(getDaemonSocketDir());
export const getFullOsSocketPath = () => {
const path = resolve(getDaemonSocketDir());

assertValidSocketPath(path);

return isWindows ? '\\\\.\\pipe\\nx\\' + path : path;
};

export const getForkedProcessOsSocketPath = (id: string) => {
let path = resolve(join(getSocketDir(), 'fp' + id + '.sock'));
return isWindows ? '\\\\.\\pipe\\nx\\' + resolve(path) : resolve(path);

assertValidSocketPath(path);

return isWindows ? '\\\\.\\pipe\\nx\\' + path : path;
};

export const getPluginOsSocketPath = (id: string) => {
let path = resolve(join(getSocketDir(true), 'plugin' + id + '.sock'));
return isWindows ? '\\\\.\\pipe\\nx\\' + resolve(path) : resolve(path);

assertValidSocketPath(path);

return isWindows ? '\\\\.\\pipe\\nx\\' + path : path;
};

function assertValidSocketPath(path: string) {
if (path.length > 95) {
throw new Error(
[
'Attempted to open socket that exceeds the maximum socket length.',
'',
`Set NX_SOCKET_DIR to a shorter path (e.g. ${
isWindows ? '%TMP%/nx-tmp' : '/tmp/nx-tmp'
}) to avoid this issue.`,
].join('\n')
);
}
}

export function killSocketOrPath(): void {
try {
unlinkSync(getFullOsSocketPath());
Expand Down
2 changes: 2 additions & 0 deletions packages/nx/src/daemon/tmp-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ function socketDirName() {
export function getSocketDir(alreadyUnique = false) {
try {
const dir =
process.env.NX_SOCKET_DIR ??
process.env.NX_DAEMON_SOCKET_DIR ??
(alreadyUnique ? tmpdir : socketDirName());
ensureDirSync(dir);

return dir;
} catch (e) {
return DAEMON_DIR_FOR_CURRENT_WORKSPACE;
Expand Down

0 comments on commit abfb25d

Please sign in to comment.