Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
6
66
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Eric Vidal
66
Commits
8cc581b4
Commit
8cc581b4
authored
3 years ago
by
Eric Vidal
Browse files
Options
Downloads
Patches
Plain Diff
handle start/down of trees asynchronously except for dependency/requiredby. At least it build
parent
781c5663
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/lib66/exec/ssexec_all.c
+483
-190
483 additions, 190 deletions
src/lib66/exec/ssexec_all.c
with
483 additions
and
190 deletions
src/lib66/exec/ssexec_all.c
+
483
−
190
View file @
8cc581b4
...
...
@@ -27,20 +27,61 @@
#include
<oblibs/sastr.h>
#include
<oblibs/obgetopt.h>
#include
<oblibs/files.h>
#include
<oblibs/graph.h>
#include
<skalibs/types.h>
#include
<skalibs/stralloc.h>
#include
<skalibs/djbunix.h>
#include
<skalibs/posixplz.h>
#include
<skalibs/tai.h>
#include
<skalibs/selfpipe.h>
#include
<skalibs/iopause.h>
#include
<66/ssexec.h>
#include
<66/constants.h>
#include
<66/tree.h>
#include
<66/utils.h>
//scandir_ok
#include
<66/db.h>
#include
<66/graph.h>
#include
<s6-rc/s6rc-servicedir.h>
#define FLAGS_STARTING 1 // starting not really up
#define FLAGS_STOPPING 2 // stopping not really down
#define FLAGS_UP 3 // really up
#define FLAGS_DOWN 4 // really down
/*
#define FLAGS_BLOCK 5 // all deps are not up/down
#define FLAGS_UNBLOCK 6 // all deps up/down
#define FLAGS_FATAL 7 // process crashed
#define FLAGS_EXITED 8 // process exited
*/
/** return 1 if set, else 0*/
#define FLAGS_ISSET(has, want) \
((~(has) & (want)) == 0)
typedef
struct
pidvertex_s
pidvertex_t
,
*
pidvertex_t_ref
;
struct
pidvertex_s
{
pid_t
pid
;
unsigned
int
vertex
;
// id at graph_hash_t struct
uint8_t
state
;
int
nedge
;
unsigned
int
*
edge
;
// array of id at graph_hash_t struct
}
;
#define PIDINDEX_ZERO { 0, 0, 0, 0, 0 }
static
pidvertex_t
*
apidvertex
;
static
unsigned
int
napid
=
0
;
static
unsigned
int
npid
=
0
;
static
int
flag
;
static
int
flag_run
;
static
void
async
(
unsigned
int
i
,
unsigned
int
what
,
ssexec_t
*
info
,
graph_t
*
graph
)
;
static
int
unsupervise
(
ssexec_t
*
info
,
int
what
)
;
static
inline
unsigned
int
lookup
(
char
const
*
const
*
table
,
char
const
*
signal
)
{
log_flow
()
;
...
...
@@ -54,113 +95,158 @@ static inline unsigned int parse_signal (char const *signal)
{
log_flow
()
;
static
char
const
*
const
signal_table
[]
=
{
static
char
const
*
const
signal_table
[]
=
{
"up"
,
"down"
,
"unsupervise"
,
0
}
;
unsigned
int
i
=
lookup
(
signal_table
,
signal
)
;
if
(
!
signal_table
[
i
])
log_usage
(
usage_all
)
;
return
i
;
unsigned
int
i
=
lookup
(
signal_table
,
signal
)
;
if
(
!
signal_table
[
i
])
log_usage
(
usage_all
)
;
return
i
;
}
int
all_doit
(
ssexec_t
*
info
,
unsigned
int
what
,
char
const
*
const
*
envp
)
static
void
redir_fd
(
void
)
{
log_flow
()
;
int
r
;
int
fd
;
while
((
fd
=
open
(
"/dev/tty"
,
O_RDWR
|
O_NOCTTY
))
>=
0
)
{
stralloc
salist
=
STRALLOC_ZERO
;
char
const
*
exclude
[
2
]
=
{
SS_LIVETREE_INIT
,
0
}
;
if
(
fd
>=
3
)
break
;
}
char
ownerstr
[
UID_FMT
]
;
size_t
ownerlen
=
uid_fmt
(
ownerstr
,
info
->
owner
)
;
ownerstr
[
ownerlen
]
=
0
;
dup2
(
fd
,
0
)
;
dup2
(
fd
,
1
)
;
dup2
(
fd
,
2
)
;
fd_close
(
fd
)
;
char
src
[
info
->
live
.
len
+
SS_STATE_LEN
+
1
+
ownerlen
+
1
+
info
->
treename
.
len
+
1
+
SS_LIVETREE_INIT_LEN
+
1
]
;
auto_strings
(
src
,
info
->
live
.
s
,
SS_STATE
,
"/"
,
ownerstr
,
"/"
,
info
->
treename
.
s
,
"/"
,
SS_LIVETREE_INIT
)
;
if
(
setsid
()
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"setsid"
)
;
r
=
scan_mode
(
src
,
S_IFREG
)
;
if
(
r
==
-
1
)
log_die
(
LOG_EXIT_SYS
,
src
,
" conflicted format"
)
;
if
(
!
r
)
{
log_warn
(
"uninitialized tree: "
,
info
->
treename
.
s
)
;
goto
freed
;
}
if
((
chdir
(
"/"
))
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"chdir"
)
;
ioctl
(
0
,
TIOCSCTTY
,
1
)
;
umask
(
022
)
;
}
src
[
info
->
live
.
len
+
SS_STATE_LEN
+
1
+
ownerlen
+
1
+
info
->
treename
.
len
]
=
0
;
if
(
!
sastr_dir_get
(
&
salist
,
src
,
exclude
,
S_IFREG
))
log_dieusys
(
LOG_EXIT_SYS
,
"get contents of directory: "
,
src
)
;
static
int
doit
(
ssexec_t
*
info
,
char
const
*
treename
,
unsigned
int
what
)
{
log_flow
()
;
int
r
,
e
=
1
;
if
(
salist
.
len
)
{
size_t
pos
=
0
,
len
=
sastr_len
(
&
salist
)
;
int
n
=
what
==
2
?
3
:
2
;
int
nargc
=
n
+
len
;
char
const
*
newargv
[
nargc
]
;
unsigned
int
m
=
0
;
info
->
treename
.
len
=
0
;
newargv
[
m
++
]
=
"fake_name"
;
if
(
what
==
2
)
newargv
[
m
++
]
=
"-u"
;
if
(
!
auto_stra
(
&
info
->
treename
,
treename
))
log_die_nomem
(
"stralloc"
)
;
FOREACH_SASTR
(
&
salist
,
pos
)
{
info
->
tree
.
len
=
0
;
newargv
[
m
++
]
=
salist
.
s
+
pos
;
}
if
(
!
auto_stra
(
&
info
->
tree
,
treename
))
log_die_nomem
(
"stralloc"
)
;
r
=
tree_sethome
(
info
)
;
if
(
r
<=
0
)
log_warnu_return
(
LOG_EXIT_ONE
,
"find tree: "
,
info
->
treename
.
s
)
;
if
(
!
tree_get_permissions
(
info
->
tree
.
s
,
info
->
owner
))
log_warn_return
(
LOG_EXIT_ONE
,
"You're not allowed to use the tree: "
,
info
->
tree
.
s
)
;
}
newargv
[
m
++
]
=
0
;
if
(
!
tree_isinitialized
(
info
->
base
.
s
,
info
->
treename
.
s
))
{
if
(
!
what
)
{
if
(
ssexec_start
(
nargc
,
newargv
,
envp
,
info
))
goto
err
;
int
nargc
=
3
;
char
const
*
newargv
[
nargc
]
;
unsigned
int
m
=
0
;
newargv
[
m
++
]
=
"fake_name"
;
newargv
[
m
++
]
=
"b"
;
newargv
[
m
++
]
=
0
;
if
(
ssexec_init
(
nargc
,
newargv
,
(
char
const
*
const
*
)
environ
,
info
))
log_warnu_return
(
LOG_EXIT_ONE
,
"initiate services of tree: "
,
info
->
treename
.
s
)
;
log_trace
(
"reload scandir: "
,
info
->
scandir
.
s
)
;
if
(
scandir_send_signal
(
info
->
scandir
.
s
,
"h"
)
<=
0
)
log_warnu_return
(
LOG_EXIT_ONE
,
"reload scandir: "
,
info
->
scandir
.
s
)
;
}
else
{
if
(
ssexec_stop
(
nargc
,
newargv
,
envp
,
info
))
goto
err
;
log_warn
(
"uninitialized tree: "
,
info
->
treename
.
s
)
;
goto
freed
;
}
}
else
log_info
(
"Empty tree: "
,
info
->
treename
.
s
,
" -- nothing to do"
)
;
freed:
stralloc_free
(
&
salist
)
;
return
1
;
err:
stralloc_free
(
&
salist
)
;
return
0
;
}
if
(
what
==
2
)
{
static
void
all_redir_fd
(
void
)
{
log_flow
()
;
if
(
unsupervise
(
info
,
what
))
goto
err
;
int
fd
;
while
((
fd
=
open
(
"/dev/tty"
,
O_RDWR
|
O_NOCTTY
))
>=
0
)
{
if
(
fd
>=
3
)
break
;
}
dup2
(
fd
,
0
)
;
dup2
(
fd
,
1
)
;
dup2
(
fd
,
2
)
;
fd_close
(
fd
)
;
}
else
{
if
(
setsid
()
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"setsid"
)
;
char
const
*
exclude
[
1
]
=
{
0
}
;
char
ownerstr
[
UID_FMT
]
;
size_t
ownerlen
=
uid_fmt
(
ownerstr
,
info
->
owner
)
;
ownerstr
[
ownerlen
]
=
0
;
if
((
chdir
(
"/"
))
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"chdir"
)
;
stralloc
salist
=
STRALLOC_ZERO
;
ioctl
(
0
,
TIOCSCTTY
,
1
)
;
char
src
[
info
->
live
.
len
+
SS_STATE_LEN
+
1
+
ownerlen
+
1
+
info
->
treename
.
len
+
1
]
;
umask
(
022
)
;
auto_strings
(
src
,
info
->
live
.
s
,
SS_STATE
,
"/"
,
ownerstr
,
"/"
,
info
->
treename
.
s
)
;
if
(
!
sastr_dir_get
(
&
salist
,
src
,
exclude
,
S_IFREG
))
log_warnusys_return
(
LOG_EXIT_ONE
,
"get contents of directory: "
,
src
)
;
if
(
salist
.
len
)
{
size_t
pos
=
0
,
len
=
sastr_len
(
&
salist
)
;
int
n
=
what
==
2
?
3
:
2
;
int
nargc
=
n
+
len
;
char
const
*
newargv
[
nargc
]
;
unsigned
int
m
=
0
;
newargv
[
m
++
]
=
"fake_name"
;
if
(
what
==
2
)
newargv
[
m
++
]
=
"-u"
;
FOREACH_SASTR
(
&
salist
,
pos
)
newargv
[
m
++
]
=
salist
.
s
+
pos
;
newargv
[
m
++
]
=
0
;
if
(
!
what
)
{
if
(
ssexec_start
(
nargc
,
newargv
,
(
char
const
*
const
*
)
environ
,
info
))
goto
err
;
}
else
{
if
(
ssexec_stop
(
nargc
,
newargv
,
(
char
const
*
const
*
)
environ
,
info
))
goto
err
;
}
}
else
log_info
(
"Empty tree: "
,
info
->
treename
.
s
,
" -- nothing to do"
)
;
stralloc_free
(
&
salist
)
;
}
freed:
e
=
0
;
err:
return
e
;
}
void
all_
unsupervise
(
ssexec_t
*
info
,
char
const
*
const
*
envp
,
int
what
)
static
int
unsupervise
(
ssexec_t
*
info
,
int
what
)
{
log_flow
()
;
...
...
@@ -168,75 +254,305 @@ void all_unsupervise(ssexec_t *info, char const *const *envp,int what)
char
const
*
exclude
[
1
]
=
{
0
}
;
char
ownerstr
[
UID_FMT
]
;
size_t
ownerlen
=
uid_fmt
(
ownerstr
,
info
->
owner
)
;
size_t
ownerlen
=
uid_fmt
(
ownerstr
,
info
->
owner
)
;
ownerstr
[
ownerlen
]
=
0
;
stralloc
salist
=
STRALLOC_ZERO
;
/** set what we need */
char
prefix
[
info
->
treename
.
len
+
2
]
;
auto_strings
(
prefix
,
info
->
treename
.
s
,
"-"
)
;
auto_strings
(
prefix
,
info
->
treename
.
s
,
"-"
)
;
char
livestate
[
info
->
live
.
len
+
SS_STATE_LEN
+
1
+
ownerlen
+
1
+
info
->
treename
.
len
+
1
]
;
auto_strings
(
livestate
,
info
->
live
.
s
,
SS_STATE
+
1
,
"/"
,
ownerstr
,
"/"
,
info
->
treename
.
s
)
;
auto_strings
(
livestate
,
info
->
live
.
s
,
SS_STATE
+
1
,
"/"
,
ownerstr
,
"/"
,
info
->
treename
.
s
)
;
/** bring down service */
if
(
!
all_doit
(
info
,
what
,
envp
))
if
(
all_doit
(
info
,
info
->
treename
.
s
,
what
))
log_warnusys
(
"stop services"
)
;
if
(
db_find_compiled_state
(
info
->
livetree
.
s
,
info
->
treename
.
s
)
>=
0
)
{
if
(
db_find_compiled_state
(
info
->
livetree
.
s
,
info
->
treename
.
s
)
>=
0
)
{
salist
.
len
=
0
;
char
livetree
[
newlen
+
info
->
treename
.
len
+
SS_SVDIRS_LEN
+
1
]
;
auto_strings
(
livetree
,
info
->
livetree
.
s
,
"/"
,
info
->
treename
.
s
,
SS_SVDIRS
)
;
auto_strings
(
livetree
,
info
->
livetree
.
s
,
"/"
,
info
->
treename
.
s
,
SS_SVDIRS
)
;
if
(
!
sastr_dir_get
(
&
salist
,
livetree
,
exclude
,
S_IFDIR
))
log_dieusys
(
LOG_EXIT_SYS
,
"get service list at: "
,
livetree
)
;
if
(
!
sastr_dir_get
(
&
salist
,
livetree
,
exclude
,
S_IFDIR
))
log_warnusys_return
(
LOG_EXIT_ONE
,
"get service list at: "
,
livetree
)
;
livetree
[
newlen
+
info
->
treename
.
len
]
=
0
;
pos
=
0
;
FOREACH_SASTR
(
&
salist
,
pos
)
{
s6rc_servicedir_unsupervise
(
livetree
,
prefix
,
salist
.
s
+
pos
,
0
)
;
s6rc_servicedir_unsupervise
(
livetree
,
prefix
,
salist
.
s
+
pos
,
0
)
;
}
char
*
realsym
=
realpath
(
livetree
,
0
)
;
if
(
!
realsym
)
log_
dieusys
(
LOG_EXIT_
SYS
,
"find realpath of: "
,
livetree
)
;
log_
warnusys_return
(
LOG_EXIT_
ONE
,
"find realpath of: "
,
livetree
)
;
if
(
rm_rf
(
realsym
)
==
-
1
)
log_
dieusys
(
LOG_EXIT_
SYS
,
"remove: "
,
realsym
)
;
log_
warnusys_return
(
LOG_EXIT_
ONE
,
"remove: "
,
realsym
)
;
free
(
realsym
)
;
if
(
rm_rf
(
livetree
)
==
-
1
)
log_
dieusys
(
LOG_EXIT_
SYS
,
"remove: "
,
livetree
)
;
log_
warnusys_return
(
LOG_EXIT_
ONE
,
"remove: "
,
livetree
)
;
/** remove the symlink itself */
unlink_void
(
livetree
)
;
}
if
(
scandir_send_signal
(
info
->
scandir
.
s
,
"h"
)
<=
0
)
log_
dieusys
(
LOG_EXIT_
SYS
,
"reload scandir: "
,
info
->
scandir
.
s
)
;
log_
warnusys_return
(
LOG_EXIT_
ONE
,
"reload scandir: "
,
info
->
scandir
.
s
)
;
/** remove /run/66/state/uid/treename directory */
log_trace
(
"delete: "
,
livestate
,
"..."
)
;
log_trace
(
"delete: "
,
livestate
,
"..."
)
;
if
(
rm_rf
(
livestate
)
<
0
)
log_
dieusys
(
LOG_EXIT_
SYS
,
"delete "
,
livestate
)
;
log_
warnusys_return
(
LOG_EXIT_
ONE
,
"delete "
,
livestate
)
;
log_info
(
"Unsupervised successfully tree: "
,
info
->
treename
.
s
)
;
log_info
(
"Unsupervised successfully tree: "
,
info
->
treename
.
s
)
;
stralloc_free
(
&
salist
)
;
return
0
;
}
int
ssexec_all
(
int
argc
,
char
const
*
const
*
argv
,
char
const
*
const
*
envp
,
ssexec_t
*
info
)
static
pidvertex_t
pidvertex_init
(
unsigned
int
len
)
{
log_flow
()
;
pidvertex_t
pidv
=
PIDINDEX_ZERO
;
pidv
.
edge
=
(
unsigned
int
*
)
malloc
(
len
*
sizeof
(
unsigned
int
))
;
graph_array_init_single
(
pidv
.
edge
,
len
)
;
return
pidv
;
}
static
void
pidvertex_free
(
pidvertex_t
*
pidv
)
{
free
(
pidv
->
edge
)
;
}
static
void
pidvertex_init_array
(
pidvertex_t
*
apidvertex
,
graph_t
*
g
,
unsigned
int
*
list
,
unsigned
int
count
,
ssexec_t
*
info
,
uint8_t
requiredby
)
{
log_flow
()
;
int
r
=
-
1
;
size_t
pos
=
0
;
for
(;
pos
<
count
;
pos
++
)
{
char
*
name
=
g
->
data
.
s
+
genalloc_s
(
graph_hash_t
,
&
g
->
hash
)[
list
[
pos
]].
vertex
;
pidvertex_t
pidv
=
pidvertex_init
(
g
->
mlen
)
;
int
r
,
what
,
shut
=
0
,
fd
;
pidv
.
nedge
=
graph_matrix_get_edge_g_sorted_list
(
pidv
.
edge
,
g
,
name
,
requiredby
)
;
size_t
statesize
,
pos
=
0
;
if
(
pidv
.
nedge
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"get sorted "
,
requiredby
?
"required by"
:
"dependency"
,
" list of tree: "
,
name
)
;
stralloc
contents
=
STRALLOC_ZERO
;
pidv
.
vertex
=
list
[
pos
]
;
if
(
pidv
.
vertex
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"get vertex id -- please make a bug report"
)
;
r
=
tree_isinitialized
(
info
->
base
.
s
,
name
)
;
if
(
r
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"read resolve file of tree: "
,
name
)
;
if
(
r
)
pidv
.
state
|=
FLAGS_UP
;
else
pidv
.
state
|=
FLAGS_DOWN
;
apidvertex
[
pos
]
=
pidv
;
}
}
static
void
pidvertex_array_free
(
pidvertex_t
*
apidvertex
,
unsigned
int
len
)
{
log_flow
()
;
size_t
pos
=
0
;
for
(;
pos
<
len
;
pos
++
)
pidvertex_free
(
&
apidvertex
[
pos
])
;
}
static
int
pidvertex_get_id
(
pidvertex_t
*
apidvertex
,
unsigned
int
id
)
{
log_flow
()
;
unsigned
int
pos
=
0
;
for
(;
pos
<
napid
;
pos
++
)
{
if
(
apidvertex
[
pos
].
vertex
==
id
)
return
(
unsigned
int
)
pos
;
}
return
-
1
;
}
static
void
async_deps
(
unsigned
int
i
,
unsigned
int
what
,
ssexec_t
*
info
,
graph_t
*
graph
)
{
log_flow
()
;
unsigned
int
pos
=
0
;
while
(
apidvertex
[
i
].
nedge
)
{
/** TODO: the pidvertex_get_id() function make a loop
* through the apidvertex array to find the corresponding
* index of the edge at the apidvertex array.
* This is clearly a waste of time and need to be optimized. */
unsigned
int
id
=
pidvertex_get_id
(
apidvertex
,
apidvertex
[
i
].
edge
[
pos
])
;
if
(
id
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"get apidvertex id -- please make a bug report"
)
;
async
(
id
,
what
,
info
,
graph
)
;
apidvertex
[
i
].
nedge
--
;
pos
++
;
}
}
static
void
async
(
unsigned
int
i
,
unsigned
int
what
,
ssexec_t
*
info
,
graph_t
*
graph
)
{
/**
* @i: apidvertex array index
* */
log_flow
()
;
int
r
;
pid_t
pid
;
char
*
treename
=
graph
->
data
.
s
+
genalloc_s
(
graph_hash_t
,
&
graph
->
hash
)[
apidvertex
[
i
].
vertex
].
vertex
;
if
(
FLAGS_ISSET
(
apidvertex
[
i
].
state
,
flag
)
||
FLAGS_ISSET
(
apidvertex
[
i
].
state
,
flag_run
))
{
pid
=
fork
()
;
if
(
pid
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"fork"
)
;
if
(
!
pid
)
{
if
(
!
apidvertex
[
i
].
nedge
)
{
/** Mark as processing */
apidvertex
[
i
].
state
|=
flag_run
;
r
=
doit
(
info
,
treename
,
what
)
;
_exit
(
r
)
;
}
else
{
async_deps
(
i
,
what
,
info
,
graph
)
;
}
}
apidvertex
[
i
].
pid
=
pid
;
}
else
{
log_trace
(
"skipping: "
,
treename
,
" -- already "
,
FLAGS_ISSET
(
flag
,
FLAGS_DOWN
)
?
"down"
:
"up"
)
;
}
return
;
}
static
int
handle_signal
(
pidvertex_t
*
apidvertex
)
{
log_flow
()
;
int
ok
=
1
;
for
(;;)
{
switch
(
selfpipe_read
())
{
case
-
1
:
log_warnusys_return
(
LOG_EXIT_ZERO
,
"selfpipe_read"
)
;
case
0
:
return
ok
;
case
SIGCHLD
:
for
(;;)
{
unsigned
int
j
=
0
;
int
wstat
;
pid_t
r
=
wait_nohang
(
&
wstat
)
;
if
(
r
<
0
)
{
if
(
errno
=
ECHILD
)
break
;
else
log_dieusys
(
LOG_EXIT_SYS
,
"wait for children"
)
;
}
else
if
(
!
r
)
break
;
for
(;
j
<
npid
;
j
++
)
if
(
apidvertex
[
j
].
pid
==
r
)
break
;
if
(
j
<
npid
)
{
if
(
!
WIFSIGNALED
(
wstat
)
&&
!
WEXITSTATUS
(
wstat
))
{
apidvertex
[
j
].
state
&=
~
flag
&
~
flag_run
;
}
else
{
ok
=
0
;
apidvertex
[
j
].
state
&=
~
flag
&
~
flag_run
;
}
apidvertex
[
j
]
=
apidvertex
[
--
npid
]
;
}
}
break
;
case
SIGTERM
:
case
SIGINT
:
log_warn
(
"received SIGINT, aborting service transition"
)
;
break
;
default
:
log_warn
(
"unexpected data in selfpipe"
)
;
}
}
return
ok
;
}
static
int
waitit
(
int
spfd
,
pidvertex_t
*
apidvertex
,
graph_t
*
graph
,
unsigned
int
what
,
tain
*
deadline
,
ssexec_t
*
info
)
{
iopause_fd
x
=
{
.
fd
=
spfd
,
.
events
=
IOPAUSE_READ
}
;
unsigned
int
e
=
1
,
pos
=
0
;
int
r
;
npid
=
napid
;
for
(;
pos
<
npid
;
pos
++
)
async
(
pos
,
what
,
info
,
graph
)
;
while
(
npid
)
{
r
=
iopause_g
(
&
x
,
1
,
deadline
)
;
if
(
r
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"iopause"
)
;
if
(
!
r
)
log_die
(
LOG_EXIT_SYS
,
"time out"
)
;
if
(
!
handle_signal
(
apidvertex
))
e
=
0
;
}
return
e
;
}
int
ssexec_all
(
int
argc
,
char
const
*
const
*
argv
,
char
const
*
const
*
envp
,
ssexec_t
*
info
)
{
int
r
,
shut
=
0
,
fd
;
tain
deadline
;
unsigned
int
what
;
uint8_t
requiredby
=
0
;
graph_t
graph
=
GRAPH_ZERO
;
{
subgetopt
l
=
SUBGETOPT_ZERO
;
...
...
@@ -257,148 +573,125 @@ int ssexec_all(int argc, char const *const *argv,char const *const *envp,ssexec_
if
(
argc
!=
1
)
log_usage
(
usage_all
)
;
if
(
info
->
timeout
)
tain_from_millisecs
(
&
deadline
,
info
->
timeout
)
;
else
deadline
=
tain_infinite_relative
;
what
=
parse_signal
(
*
argv
)
;
if
((
scandir_ok
(
info
->
scandir
.
s
))
<=
0
)
log_die
(
LOG_EXIT_SYS
,
"scandir: "
,
info
->
scandir
.
s
,
" is not running"
)
;
if
(
what
)
{
char
ste
[
info
->
base
.
len
+
SS_SYSTEM_LEN
+
SS_STATE_LEN
+
1
]
;
auto_strings
(
ste
,
info
->
base
.
s
,
SS_SYSTEM
,
SS_STATE
)
;
requiredby
=
1
;
flag
=
FLAGS_UP
;
flag_run
=
FLAGS_STOPPING
;
r
=
scan_mode
(
ste
,
S_IFREG
)
;
if
(
r
<
0
)
log_die
(
LOG_EXIT_SYS
,
"conflict format for: "
,
ste
)
;
if
(
!
r
)
log_dieusys
(
LOG_EXIT_SYS
,
"find: "
,
ste
)
;
}
else
{
/** only one tree?*/
if
(
info
->
treename
.
len
)
{
if
(
!
auto_stra
(
&
contents
,
info
->
treename
.
s
))
log_die_nomem
(
"stralloc"
)
;
flag
=
FLAGS_DOWN
;
flag_run
=
FLAGS_STARTING
;
}
else
{
statesize
=
file_get_size
(
ste
)
;
r
=
openreadfileclose
(
ste
,
&
contents
,
statesize
)
;
if
(
!
r
)
log_die
usys
(
LOG_EXIT_SYS
,
"
open: "
,
ste
)
;
if
((
scandir_ok
(
info
->
scandir
.
s
))
<=
0
)
log_die
(
LOG_EXIT_SYS
,
"
scandir: "
,
info
->
scandir
.
s
,
" is not running"
)
;
/** ensure that we have an empty line at the end of the string*/
if
(
!
stralloc_cats
(
&
contents
,
"
\n
"
)
||
!
stralloc_0
(
&
contents
))
log_die_nomem
(
"stralloc"
)
;
if
(
!
graph_build_g
(
&
graph
,
info
->
base
.
s
,
info
->
treename
.
s
,
DATA_TREE
))
log_dieu
(
LOG_EXIT_SYS
,
"build the graph"
)
;
if
(
!
sastr_clean_element
(
&
contents
))
{
log_info
(
"nothing to do"
)
;
goto
end
;
}
/** initialize and allocate apidvertex array */
}
pidvertex_t
apidv
[
graph
.
mlen
]
;
if
(
shut
)
{
pid_t
dpid
;
int
wstat
=
0
;
apidvertex
=
apidv
;
dpid
=
fork
()
;
/** only on tree */
if
(
info
->
treename
.
len
)
{
if
(
dpid
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"fork"
)
;
else
if
(
dpid
>
0
)
{
if
(
waitpid_nointr
(
dpid
,
&
wstat
,
0
)
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"wait for child"
)
;
unsigned
int
*
alist
;
if
(
wstat
)
log_die
(
LOG_EXIT_SYS
,
"child fail"
)
;
alist
=
(
unsigned
int
*
)
malloc
(
graph
.
mlen
*
sizeof
(
unsigned
int
))
;
goto
end
;
}
else
all_redir_fd
()
;
}
graph_array_init_single
(
alist
,
graph
.
mlen
)
;
/** Down/unsupervise process? reverse in that case to respect tree start order*/
if
(
what
)
if
(
!
sastr_reverse
(
&
contents
))
log_dieu
(
LOG_EXIT_SYS
,
"reserve tree order"
)
;
napid
=
graph_matrix_get_edge_g_sorted_list
(
alist
,
&
graph
,
info
->
treename
.
s
,
requiredby
)
;
FOREACH_SASTR
(
&
contents
,
pos
)
{
if
(
napid
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"get "
,
requiredby
?
"required"
:
"dependencies"
,
" sorted list of: "
,
info
->
treename
.
s
)
;
info
->
treename
.
len
=
0
;
alist
[
napid
++
]
=
(
unsigned
int
)
graph_hash_vertex_get_id
(
&
graph
,
info
->
treename
.
s
)
;
if
(
!
auto_stra
(
&
info
->
treename
,
contents
.
s
+
pos
))
log_die_nomem
(
"stralloc"
)
;
pidvertex_init_array
(
apidvertex
,
&
graph
,
alist
,
napid
,
info
,
requiredby
)
;
info
->
tree
.
len
=
0
;
free
(
alist
)
;
if
(
!
auto_stra
(
&
info
->
tree
,
contents
.
s
+
pos
))
log_die_nomem
(
"stralloc"
)
;
/**
*
*
*
*
*
*
*
* Attention ici avec le nouveau format de tree_sethome()
*
*
*
*
*
*
*
*
*
*
*
*
* */
r
=
tree_sethome
(
info
)
;
if
(
r
<=
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"find tree: "
,
info
->
treename
.
s
)
;
}
else
{
if
(
!
tree_get_permissions
(
info
->
tree
.
s
,
info
->
owner
))
log_die
(
LOG_EXIT_USER
,
"You're not allowed to use the tree: "
,
info
->
tree
.
s
)
;
napid
=
graph
.
sort_count
;
if
(
!
what
)
{
int
nargc
=
3
;
char
const
*
newargv
[
nargc
]
;
unsigned
int
m
=
0
;
pidvertex_init_array
(
apidvertex
,
&
graph
,
graph
.
sort
,
graph
.
sort_count
,
info
,
requiredby
)
;
}
newargv
[
m
++
]
=
"fake_name"
;
newargv
[
m
++
]
=
"b"
;
newargv
[
m
++
]
=
0
;
if
(
shut
)
{
pid_t
pid
;
int
wstat
=
0
;
if
(
ssexec_init
(
nargc
,
newargv
,
envp
,
info
))
log_dieu
(
LOG_EXIT_SYS
,
"initiate services of tree: "
,
info
->
treename
.
s
)
;
pid
=
fork
()
;
log_trace
(
"reload scandir: "
,
info
->
scandir
.
s
)
;
if
(
scandir_send_signal
(
info
->
scandir
.
s
,
"h"
)
<=
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"reload scandir: "
,
info
->
scandir
.
s
)
;
}
if
(
pid
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"fork"
)
;
if
(
what
<
2
)
{
if
(
!
pid
)
{
if
(
!
all_doit
(
info
,
what
,
envp
))
log_dieu
(
LOG_EXIT_SYS
,(
what
)
?
"start"
:
"stop"
,
" services of tree: "
,
info
->
treename
.
s
)
;
redir_fd
()
;
}
else
{
all_unsupervise
(
info
,
envp
,
what
)
;
if
(
waitpid_nointr
(
pid
,
&
wstat
,
0
)
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"wait for child"
)
;
if
(
wstat
)
log_die
(
LOG_EXIT_SYS
,
"child fail"
)
;
r
=
1
;
goto
end
;
}
}
tain_now_set_stopwatch_g
()
;
tain_add_g
(
&
deadline
,
&
deadline
)
;
int
spfd
=
selfpipe_init
()
;
if
(
spfd
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"selfpipe_init"
)
;
if
(
!
selfpipe_trap
(
SIGCHLD
)
||
!
selfpipe_trap
(
SIGINT
)
||
!
selfpipe_trap
(
SIGTERM
))
log_dieusys
(
LOG_EXIT_SYS
,
"selfpipe_trap"
)
;
r
=
waitit
(
spfd
,
apidvertex
,
&
graph
,
what
,
&
deadline
,
info
)
;
end:
if
(
shut
)
{
selfpipe_finish
()
;
if
(
shut
)
{
while
((
fd
=
open
(
"/dev/tty"
,
O_RDWR
|
O_NOCTTY
))
>=
0
)
{
if
(
fd
>=
3
)
break
;
}
if
(
fd
>=
3
)
break
;
dup2
(
fd
,
0
)
;
dup2
(
fd
,
1
)
;
dup2
(
fd
,
2
)
;
fd_close
(
fd
)
;
}
stralloc_free
(
&
contents
)
;
graph_free_all
(
&
graph
)
;
pidvertex_array_free
(
apidvertex
,
napid
)
;
return
0
;
return
(
!
r
)
?
111
:
0
;
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment