@@ -11,80 +11,122 @@ import express from 'express';
11
11
import { utilityProcess } from 'electron' ;
12
12
import state from '../state.js' ;
13
13
import { notifyLaravel } from "../utils.js" ;
14
- import { getDefaultEnvironmentVariables , getDefaultPhpIniSettings } from "../php.js" ;
14
+ import { getAppPath , getDefaultEnvironmentVariables , getDefaultPhpIniSettings , runningSecureBuild } from "../php.js" ;
15
15
import killSync from "kill-sync" ;
16
16
import { fileURLToPath } from "url" ;
17
+ import { join } from "path" ;
17
18
const router = express . Router ( ) ;
18
19
function startProcess ( settings ) {
19
- const { alias, cmd, cwd, env, persistent } = settings ;
20
+ const { alias, cmd, cwd, env, persistent, spawnTimeout = 30000 } = settings ;
20
21
if ( getProcess ( alias ) !== undefined ) {
21
22
return state . processes [ alias ] ;
22
23
}
23
- const proc = utilityProcess . fork ( fileURLToPath ( new URL ( '../../electron-plugin/dist/server/childProcess.js' , import . meta. url ) ) , cmd , {
24
- cwd,
25
- stdio : 'pipe' ,
26
- serviceName : alias ,
27
- env : Object . assign ( Object . assign ( { } , process . env ) , env )
28
- } ) ;
29
- proc . stdout . on ( 'data' , ( data ) => {
30
- notifyLaravel ( 'events' , {
31
- event : 'Native\\Laravel\\Events\\ChildProcess\\MessageReceived' ,
32
- payload : {
33
- alias,
34
- data : data . toString ( ) ,
24
+ try {
25
+ const proc = utilityProcess . fork ( fileURLToPath ( new URL ( '../../electron-plugin/dist/server/childProcess.js' , import . meta. url ) ) , cmd , {
26
+ cwd,
27
+ stdio : 'pipe' ,
28
+ serviceName : alias ,
29
+ env : Object . assign ( Object . assign ( { } , process . env ) , env )
30
+ } ) ;
31
+ const startTimeout = setTimeout ( ( ) => {
32
+ if ( ! state . processes [ alias ] || ! state . processes [ alias ] . pid ) {
33
+ console . error ( `Process [${ alias } ] failed to start within timeout period` ) ;
34
+ try {
35
+ proc . kill ( ) ;
36
+ }
37
+ catch ( e ) {
38
+ }
39
+ notifyLaravel ( 'events' , {
40
+ event : 'Native\\Laravel\\Events\\ChildProcess\\StartupError' ,
41
+ payload : {
42
+ alias,
43
+ error : 'Startup timeout exceeded' ,
44
+ }
45
+ } ) ;
35
46
}
47
+ } , spawnTimeout ) ;
48
+ proc . stdout . on ( 'data' , ( data ) => {
49
+ notifyLaravel ( 'events' , {
50
+ event : 'Native\\Laravel\\Events\\ChildProcess\\MessageReceived' ,
51
+ payload : {
52
+ alias,
53
+ data : data . toString ( ) ,
54
+ }
55
+ } ) ;
36
56
} ) ;
37
- } ) ;
38
- proc . stderr . on ( 'data' , ( data ) => {
39
- console . error ( 'Error received from process [' + alias + ']:' , data . toString ( ) ) ;
40
- notifyLaravel ( 'events' , {
41
- event : 'Native\\Laravel\\Events\\ChildProcess\\ErrorReceived' ,
42
- payload : {
43
- alias,
44
- data : data . toString ( ) ,
57
+ proc . stderr . on ( 'data' , ( data ) => {
58
+ console . error ( 'Process [' + alias + '] ERROR:' , data . toString ( ) . trim ( ) ) ;
59
+ notifyLaravel ( 'events' , {
60
+ event : 'Native\\Laravel\\Events\\ChildProcess\\ErrorReceived' ,
61
+ payload : {
62
+ alias,
63
+ data : data . toString ( ) ,
64
+ }
65
+ } ) ;
66
+ } ) ;
67
+ proc . on ( 'spawn' , ( ) => {
68
+ clearTimeout ( startTimeout ) ;
69
+ console . log ( 'Process [' + alias + '] spawned!' ) ;
70
+ state . processes [ alias ] = {
71
+ pid : proc . pid ,
72
+ proc,
73
+ settings
74
+ } ;
75
+ notifyLaravel ( 'events' , {
76
+ event : 'Native\\Laravel\\Events\\ChildProcess\\ProcessSpawned' ,
77
+ payload : [ alias , proc . pid ]
78
+ } ) ;
79
+ } ) ;
80
+ proc . on ( 'exit' , ( code ) => {
81
+ clearTimeout ( startTimeout ) ;
82
+ console . log ( `Process [${ alias } ] exited with code [${ code } ].` ) ;
83
+ notifyLaravel ( 'events' , {
84
+ event : 'Native\\Laravel\\Events\\ChildProcess\\ProcessExited' ,
85
+ payload : {
86
+ alias,
87
+ code,
88
+ }
89
+ } ) ;
90
+ const settings = Object . assign ( { } , getSettings ( alias ) ) ;
91
+ delete state . processes [ alias ] ;
92
+ if ( settings === null || settings === void 0 ? void 0 : settings . persistent ) {
93
+ console . log ( 'Process [' + alias + '] watchdog restarting...' ) ;
94
+ setTimeout ( ( ) => startProcess ( settings ) , 1000 ) ;
45
95
}
46
96
} ) ;
47
- } ) ;
48
- proc . on ( 'spawn' , ( ) => {
49
- console . log ( 'Process [' + alias + '] spawned!' ) ;
50
- state . processes [ alias ] = {
51
- pid : proc . pid ,
97
+ return {
98
+ pid : null ,
52
99
proc,
53
100
settings
54
101
} ;
102
+ }
103
+ catch ( error ) {
104
+ console . error ( `Failed to create process [${ alias } ]: ${ error . message } ` ) ;
55
105
notifyLaravel ( 'events' , {
56
- event : 'Native\\Laravel\\Events\\ChildProcess\\ProcessSpawned' ,
57
- payload : [ alias , proc . pid ]
58
- } ) ;
59
- } ) ;
60
- proc . on ( 'exit' , ( code ) => {
61
- console . log ( `Process [${ alias } ] exited with code [${ code } ].` ) ;
62
- notifyLaravel ( 'events' , {
63
- event : 'Native\\Laravel\\Events\\ChildProcess\\ProcessExited' ,
106
+ event : 'Native\\Laravel\\Events\\ChildProcess\\StartupError' ,
64
107
payload : {
65
108
alias,
66
- code ,
109
+ error : error . toString ( ) ,
67
110
}
68
111
} ) ;
69
- const settings = Object . assign ( { } , getSettings ( alias ) ) ;
70
- delete state . processes [ alias ] ;
71
- if ( settings . persistent ) {
72
- console . log ( 'Process [' + alias + '] watchdog restarting...' ) ;
73
- startProcess ( settings ) ;
74
- }
75
- } ) ;
76
- return {
77
- pid : null ,
78
- proc,
79
- settings
80
- } ;
112
+ return {
113
+ pid : null ,
114
+ proc : null ,
115
+ settings,
116
+ error : error . message
117
+ } ;
118
+ }
81
119
}
82
120
function startPhpProcess ( settings ) {
83
121
const defaultEnv = getDefaultEnvironmentVariables ( state . randomSecret , state . electronApiPort ) ;
84
- const iniSettings = Object . assign ( Object . assign ( { } , getDefaultPhpIniSettings ( ) ) , state . phpIni ) ;
122
+ const customIniSettings = settings . iniSettings || { } ;
123
+ const iniSettings = Object . assign ( Object . assign ( Object . assign ( { } , getDefaultPhpIniSettings ( ) ) , state . phpIni ) , customIniSettings ) ;
85
124
const iniArgs = Object . keys ( iniSettings ) . map ( key => {
86
125
return [ '-d' , `${ key } =${ iniSettings [ key ] } ` ] ;
87
126
} ) . flat ( ) ;
127
+ if ( settings . cmd [ 0 ] === 'artisan' && runningSecureBuild ( ) ) {
128
+ settings . cmd . unshift ( join ( getAppPath ( ) , 'build' , '__nativephp_app_bundle' ) ) ;
129
+ }
88
130
settings = Object . assign ( Object . assign ( { } , settings ) , { cmd : [ state . php , ...iniArgs , ...settings . cmd ] , env : Object . assign ( Object . assign ( { } , settings . env ) , defaultEnv ) } ) ;
89
131
return startProcess ( settings ) ;
90
132
}
0 commit comments