Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F103765438
PhabricatorAphlictManagementWorkflow.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Mar 4, 15:04
Size
5 KB
Mime Type
text/x-php
Expires
Thu, Mar 6, 15:04 (2 d)
Engine
blob
Format
Raw Data
Handle
24637903
Attached To
rPH Phabricator
PhabricatorAphlictManagementWorkflow.php
View Options
<?php
abstract
class
PhabricatorAphlictManagementWorkflow
extends
PhabricatorManagementWorkflow
{
final
public
function
getPIDPath
()
{
return
PhabricatorEnv
::
getEnvConfig
(
'notification.pidfile'
);
}
final
public
function
getPID
()
{
$pid
=
null
;
if
(
Filesystem
::
pathExists
(
$this
->
getPIDPath
()))
{
$pid
=
(
int
)
Filesystem
::
readFile
(
$this
->
getPIDPath
());
}
return
$pid
;
}
final
public
function
cleanup
(
$signo
=
'?'
)
{
global
$g_future
;
if
(
$g_future
)
{
$g_future
->
resolveKill
();
$g_future
=
null
;
}
Filesystem
::
remove
(
$this
->
getPIDPath
());
exit
(
1
);
}
public
static
function
requireExtensions
()
{
self
::
mustHaveExtension
(
'pcntl'
);
self
::
mustHaveExtension
(
'posix'
);
}
private
static
function
mustHaveExtension
(
$ext
)
{
if
(!
extension_loaded
(
$ext
))
{
echo
"ERROR: The PHP extension '{$ext}' is not installed. You must "
.
"install it to run aphlict on this machine.
\n
"
;
exit
(
1
);
}
$extension
=
new
ReflectionExtension
(
$ext
);
foreach
(
$extension
->
getFunctions
()
as
$function
)
{
$function
=
$function
->
name
;
if
(!
function_exists
(
$function
))
{
echo
"ERROR: The PHP function {$function}() is disabled. You must "
.
"enable it to run aphlict on this machine.
\n
"
;
exit
(
1
);
}
}
}
final
protected
function
willLaunch
()
{
$console
=
PhutilConsole
::
getConsole
();
$pid
=
$this
->
getPID
();
if
(
$pid
)
{
$console
->
writeErr
(
"Unable to start notifications server because it is already "
.
"running.
\n
"
);
exit
(
1
);
}
if
(
posix_getuid
()
!=
0
)
{
$console
->
writeErr
(
"You must run this script as root; the Aphlict server needs to bind "
.
"to privileged ports.
\n
"
);
exit
(
1
);
}
if
(!
Filesystem
::
binaryExists
(
'node'
))
{
$console
->
writeErr
(
"`node` is not in
\$
PATH. You must install Node.js to run the Aphlict "
.
"server.
\n
"
);
exit
(
1
);
}
}
final
protected
function
launch
(
$debug
=
false
)
{
$console
=
PhutilConsole
::
getConsole
();
if
(
$debug
)
{
$console
->
writeOut
(
pht
(
"Starting Aphlict server in foreground...
\n
"
));
}
else
{
Filesystem
::
writeFile
(
$this
->
getPIDPath
(),
getmypid
());
}
$server_uri
=
PhabricatorEnv
::
getEnvConfig
(
'notification.server-uri'
);
$server_uri
=
new
PhutilURI
(
$server_uri
);
$client_uri
=
PhabricatorEnv
::
getEnvConfig
(
'notification.client-uri'
);
$client_uri
=
new
PhutilURI
(
$client_uri
);
$user
=
PhabricatorEnv
::
getEnvConfig
(
'notification.user'
);
$log
=
PhabricatorEnv
::
getEnvConfig
(
'notification.log'
);
$server_argv
=
array
();
$server_argv
[]
=
csprintf
(
'--port=%s'
,
$client_uri
->
getPort
());
$server_argv
[]
=
csprintf
(
'--admin=%s'
,
$server_uri
->
getPort
());
$server_argv
[]
=
csprintf
(
'--host=%s'
,
$server_uri
->
getDomain
());
if
(
$user
)
{
$server_argv
[]
=
csprintf
(
'--user=%s'
,
$user
);
}
if
(!
$debug
)
{
$server_argv
[]
=
csprintf
(
'--log=%s'
,
$log
);
}
$command
=
csprintf
(
'node %s %C'
,
dirname
(
__FILE__
).
'/../../../../support/aphlict/server/aphlict_server.js'
,
implode
(
' '
,
$server_argv
));
if
(!
$debug
)
{
declare
(
ticks
=
1
);
pcntl_signal
(
SIGINT
,
array
(
$this
,
'cleanup'
));
pcntl_signal
(
SIGTERM
,
array
(
$this
,
'cleanup'
));
}
register_shutdown_function
(
array
(
$this
,
'cleanup'
));
if
(
$debug
)
{
$console
->
writeOut
(
"Launching server:
\n\n
$ "
.
$command
.
"
\n\n
"
);
$err
=
phutil_passthru
(
'%C'
,
$command
);
$console
->
writeOut
(
">>> Server exited!
\n
"
);
exit
(
$err
);
}
else
{
while
(
true
)
{
global
$g_future
;
$g_future
=
new
ExecFuture
(
'exec %C'
,
$command
);
$g_future
->
resolve
();
// If the server exited, wait a couple of seconds and restart it.
unset
(
$g_future
);
sleep
(
2
);
}
}
}
/* -( Commands )----------------------------------------------------------- */
final
protected
function
executeStartCommand
()
{
$console
=
PhutilConsole
::
getConsole
();
$this
->
willLaunch
();
$pid
=
pcntl_fork
();
if
(
$pid
<
0
)
{
throw
new
Exception
(
'Failed to fork()!'
);
}
else
if
(
$pid
)
{
$console
->
writeErr
(
pht
(
"Aphlict Server started.
\n
"
));
exit
(
0
);
}
// When we fork, the child process will inherit its parent's set of open
// file descriptors. If the parent process of bin/aphlict is waiting for
// bin/aphlict's file descriptors to close, it will be stuck waiting on
// the daemonized process. (This happens if e.g. bin/aphlict is started
// in another script using passthru().)
fclose
(
STDOUT
);
fclose
(
STDERR
);
$this
->
launch
();
return
0
;
}
final
protected
function
executeStopCommand
()
{
$console
=
PhutilConsole
::
getConsole
();
$pid
=
$this
->
getPID
();
if
(!
$pid
)
{
$console
->
writeErr
(
pht
(
"Aphlict is not running.
\n
"
));
return
0
;
}
$console
->
writeErr
(
pht
(
"Stopping Aphlict Server (%s)...
\n
"
,
$pid
));
posix_kill
(
$pid
,
SIGINT
);
$start
=
time
();
do
{
if
(!
PhabricatorDaemonReference
::
isProcessRunning
(
$pid
))
{
$console
->
writeOut
(
"%s
\n
"
,
pht
(
'Aphlict Server (%s) exited normally.'
,
$pid
));
$pid
=
null
;
break
;
}
usleep
(
100000
);
}
while
(
time
()
<
$start
+
5
);
if
(
$pid
)
{
$console
->
writeErr
(
pht
(
'Sending %s a SIGKILL.'
,
$pid
).
"
\n
"
);
posix_kill
(
$pid
,
SIGKILL
);
unset
(
$pid
);
}
Filesystem
::
remove
(
$this
->
getPIDPath
());
return
0
;
}
}
Event Timeline
Log In to Comment