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
c9c16cad
Commit
c9c16cad
authored
2 years ago
by
Eric Vidal
Browse files
Options
Downloads
Patches
Plain Diff
thanks for your service
parent
5490511f
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/lib66/exec/deps-lib/deps
+0
-1
0 additions, 1 deletion
src/lib66/exec/deps-lib/deps
src/lib66/exec/ssexec_all.c
+0
-1006
0 additions, 1006 deletions
src/lib66/exec/ssexec_all.c
with
0 additions
and
1007 deletions
src/lib66/exec/deps-lib/deps
+
0
−
1
View file @
c9c16cad
ssexec_all.o
ssexec_boot.o
ssexec_copy.o
ssexec_disable.o
...
...
This diff is collapsed.
Click to expand it.
src/lib66/exec/ssexec_all.c
deleted
100644 → 0
+
0
−
1006
View file @
5490511f
/*
* ssexec_all.c
*
* Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
*
* All rights reserved.
*
* This file is part of Obarun. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution.
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file./
*/
#include
<sys/stat.h>
//S_IFREG,umask
#include
<sys/types.h>
//pid_t
#include
<fcntl.h>
//O_RDWR
#include
<unistd.h>
//dup2,setsid,chdir,fork
#include
<sys/ioctl.h>
#include
<stdint.h>
//uint8_t
#include
<stdlib.h>
//realpath
#include
<string.h>
//strdup
#include
<oblibs/string.h>
#include
<oblibs/types.h>
#include
<oblibs/log.h>
#include
<oblibs/sastr.h>
#include
<oblibs/obgetopt.h>
#include
<oblibs/files.h>
#include
<oblibs/graph.h>
#include
<oblibs/directory.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/sig.h>
#include
<skalibs/iopause.h>
#include
<66/ssexec.h>
#include
<66/constants.h>
#include
<66/tree.h>
#include
<66/svc.h>
//scandir_ok
#include
<66/utils.h>
#include
<66/graph.h>
#include
<s6/ftrigr.h>
#include
<s6/ftrigw.h>
#define FLAGS_STARTING 1 // 1 starting not really up
#define FLAGS_STOPPING (1 << 1) // 2 stopping not really down
#define FLAGS_UP (1 << 2) // 4 really up
#define FLAGS_DOWN (1 << 3) // 8 really down
#define FLAGS_BLOCK (1 << 4) // 16 all deps are not up/down
#define FLAGS_UNBLOCK (1 << 5) // 32 all deps up/down
#define FLAGS_FATAL (1 << 6) // 64 process crashed
static
unsigned
int
napid
=
0
;
static
unsigned
int
npid
=
0
;
static
resolve_tree_t_ref
pares
=
0
;
static
unsigned
int
*
pareslen
=
0
;
static
uint8_t
reloadmsg
=
0
;
typedef
struct
pidtree_s
pidtree_t
,
*
pidtree_t_ref
;
struct
pidtree_s
{
int
pipe
[
2
]
;
pid_t
pid
;
int
aresid
;
// id at array ares
unsigned
int
vertex
;
// id at graph_hash_t struct
uint8_t
state
;
int
nedge
;
unsigned
int
edge
[
SS_MAX_SERVICE
+
1
]
;
// array of id at graph_hash_t struct
int
nnotif
;
/** id at graph_hash_t struct of depends/requiredby service
* to notify when a tree is started/stopped */
unsigned
int
notif
[
SS_MAX_SERVICE
+
1
]
;
}
;
#define PIDTREE_ZERO { { -1, -1 }, -1, -1, 0, 0, 0, { 0 } }
typedef
enum
fifo_e
fifo_t
,
*
fifo_t_ref
;
enum
fifo_e
{
FIFO_u
=
0
,
FIFO_U
,
FIFO_d
,
FIFO_D
,
FIFO_F
,
FIFO_b
,
FIFO_B
}
;
typedef
enum
tree_action_e
tree_action_t
,
*
tree_action_t_ref
;
enum
tree_action_e
{
TREE_ACTION_GOTIT
=
0
,
TREE_ACTION_WAIT
,
TREE_ACTION_FATAL
,
TREE_ACTION_UNKNOWN
}
;
static
const
unsigned
char
actions
[
2
][
7
]
=
{
// u U d D F b B
{
TREE_ACTION_WAIT
,
TREE_ACTION_GOTIT
,
TREE_ACTION_UNKNOWN
,
TREE_ACTION_UNKNOWN
,
TREE_ACTION_FATAL
,
TREE_ACTION_WAIT
,
TREE_ACTION_WAIT
},
// !what -> up
{
TREE_ACTION_UNKNOWN
,
TREE_ACTION_UNKNOWN
,
TREE_ACTION_WAIT
,
TREE_ACTION_GOTIT
,
TREE_ACTION_FATAL
,
TREE_ACTION_WAIT
,
TREE_ACTION_WAIT
}
// what -> down
}
;
// convert signal into enum number
static
const
unsigned
int
char2enum
[
128
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//8
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//16
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//24
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//32
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//40
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//48
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//56
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//64
0
,
0
,
FIFO_B
,
0
,
FIFO_D
,
0
,
FIFO_F
,
0
,
//72
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//80
0
,
0
,
0
,
0
,
0
,
FIFO_U
,
0
,
0
,
//88
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//96
0
,
0
,
FIFO_b
,
0
,
FIFO_d
,
0
,
0
,
0
,
//104
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
//112
0
,
0
,
0
,
0
,
0
,
FIFO_u
,
0
,
0
,
//120
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
//128
}
;
static
inline
unsigned
int
lookup
(
char
const
*
const
*
table
,
char
const
*
signal
)
{
log_flow
()
;
unsigned
int
i
=
0
;
for
(;
table
[
i
]
;
i
++
)
if
(
!
strcmp
(
signal
,
table
[
i
]))
break
;
return
i
;
}
static
inline
unsigned
int
parse_signal
(
char
const
*
signal
)
{
log_flow
()
;
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
;
}
static
void
all_redir_fd
(
void
)
{
log_flow
()
;
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
)
;
if
(
setsid
()
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"setsid"
)
;
if
((
chdir
(
"/"
))
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"chdir"
)
;
ioctl
(
0
,
TIOCSCTTY
,
1
)
;
umask
(
022
)
;
}
void
tree_resolve_array_free
(
resolve_tree_t
*
ares
,
unsigned
int
areslen
)
{
unsigned
int
pos
=
0
;
for
(;
pos
<
areslen
;
pos
++
)
stralloc_free
(
&
ares
[
pos
].
sa
)
;
}
static
inline
void
kill_all
(
pidtree_t
*
apidt
)
{
log_flow
()
;
unsigned
int
j
=
napid
;
while
(
j
--
)
kill
(
apidt
[
j
].
pid
,
SIGKILL
)
;
}
static
pidtree_t
pidtree_init
(
unsigned
int
len
)
{
log_flow
()
;
pidtree_t
pids
=
PIDTREE_ZERO
;
if
(
len
>
SS_MAX_SERVICE
)
log_die
(
LOG_EXIT_SYS
,
"too many trees"
)
;
graph_array_init_single
(
pids
.
edge
,
len
)
;
return
pids
;
}
static
int
pidtree_get_id
(
pidtree_t
*
apidt
,
unsigned
int
id
)
{
log_flow
()
;
unsigned
int
pos
=
0
;
for
(;
pos
<
napid
;
pos
++
)
{
if
(
apidt
[
pos
].
vertex
==
id
)
return
(
unsigned
int
)
pos
;
}
return
-
1
;
}
static
void
notify
(
pidtree_t
*
apidt
,
unsigned
int
pos
,
char
const
*
sig
,
unsigned
int
what
)
{
log_flow
()
;
unsigned
int
i
=
0
,
idx
=
0
;
char
fmt
[
UINT_FMT
]
;
uint8_t
flag
=
what
?
FLAGS_DOWN
:
FLAGS_UP
;
for
(;
i
<
apidt
[
pos
].
nnotif
;
i
++
)
{
for
(
idx
=
0
;
idx
<
napid
;
idx
++
)
{
if
(
apidt
[
pos
].
notif
[
i
]
==
apidt
[
idx
].
vertex
&&
!
FLAGS_ISSET
(
apidt
[
idx
].
state
,
flag
))
{
size_t
nlen
=
uint_fmt
(
fmt
,
apidt
[
pos
].
aresid
)
;
fmt
[
nlen
]
=
0
;
size_t
len
=
nlen
+
1
+
2
;
char
s
[
len
+
1
]
;
auto_strings
(
s
,
fmt
,
":"
,
sig
,
"@"
)
;
log_trace
(
"sends notification "
,
sig
,
" to: "
,
pares
[
apidt
[
idx
].
aresid
].
sa
.
s
+
pares
[
apidt
[
idx
].
aresid
].
name
,
" from: "
,
pares
[
apidt
[
pos
].
aresid
].
sa
.
s
+
pares
[
apidt
[
pos
].
aresid
].
name
)
;
if
(
write
(
apidt
[
idx
].
pipe
[
1
],
s
,
strlen
(
s
))
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"send notif to: "
,
pares
[
apidt
[
idx
].
aresid
].
sa
.
s
+
pares
[
apidt
[
idx
].
aresid
].
name
)
;
}
}
}
}
/**
* @what: up or down
* @success: 0 fail, 1 win
* */
static
void
announce
(
unsigned
int
pos
,
pidtree_t
*
apidt
,
char
const
*
base
,
unsigned
int
what
,
unsigned
int
success
,
unsigned
int
exitcode
)
{
log_flow
()
;
char
fmt
[
UINT_FMT
]
;
char
const
*
treename
=
pares
[
apidt
[
pos
].
aresid
].
sa
.
s
+
pares
[
apidt
[
pos
].
aresid
].
name
;
resolve_tree_t
tres
=
RESOLVE_TREE_ZERO
;
resolve_wrapper_t_ref
wres
=
resolve_set_struct
(
DATA_TREE
,
&
tres
)
;
uint8_t
flag
=
what
?
FLAGS_DOWN
:
FLAGS_UP
;
if
(
!
resolve_modify_field_g
(
wres
,
base
,
treename
,
E_RESOLVE_TREE_INIT
,
what
?
(
success
?
"1"
:
"0"
)
:
(
success
?
"0"
:
"1"
)))
log_dieusys
(
LOG_EXIT_SYS
,
"modify resolve file of: "
,
treename
)
;
if
(
success
)
{
notify
(
apidt
,
pos
,
"F"
,
what
)
;
fmt
[
uint_fmt
(
fmt
,
exitcode
)]
=
0
;
log_1_warnu
(
reloadmsg
==
0
?
"start"
:
reloadmsg
>
1
?
"unsupervise"
:
what
==
0
?
"start"
:
"stop"
,
" tree: "
,
treename
,
" -- exited with signal: "
,
fmt
)
;
FLAGS_SET
(
apidt
[
pos
].
state
,
FLAGS_BLOCK
|
FLAGS_FATAL
)
;
}
else
{
notify
(
apidt
,
pos
,
what
?
"D"
:
"U"
,
what
)
;
FLAGS_CLEAR
(
apidt
[
pos
].
state
,
FLAGS_BLOCK
)
;
FLAGS_SET
(
apidt
[
pos
].
state
,
flag
|
FLAGS_UNBLOCK
)
;
log_info
(
"Successfully "
,
reloadmsg
==
0
?
"started"
:
reloadmsg
>
1
?
"unsupervised"
:
what
==
0
?
"started"
:
"stopped"
,
" tree: "
,
treename
)
;
}
resolve_free
(
wres
)
;
}
static
void
pidtree_init_array
(
unsigned
int
*
list
,
unsigned
int
listlen
,
pidtree_t
*
apidt
,
graph_t
*
g
,
resolve_tree_t
*
ares
,
unsigned
int
areslen
,
ssexec_t
*
info
,
uint8_t
requiredby
)
{
log_flow
()
;
int
r
=
0
;
unsigned
int
pos
=
0
;
for
(;
pos
<
listlen
;
pos
++
)
{
pidtree_t
pids
=
pidtree_init
(
g
->
mlen
)
;
char
*
name
=
g
->
data
.
s
+
genalloc_s
(
graph_hash_t
,
&
g
->
hash
)[
list
[
pos
]].
vertex
;
pids
.
aresid
=
tree_resolve_array_search
(
ares
,
areslen
,
name
)
;
if
(
pids
.
aresid
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"find ares id of: "
,
name
,
" -- please make a bug reports"
)
;
pids
.
nedge
=
graph_matrix_get_edge_g_sorted_list
(
pids
.
edge
,
g
,
name
,
requiredby
,
1
)
;
if
(
pids
.
nedge
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"get sorted "
,
requiredby
?
"required by"
:
"dependency"
,
" list of tree: "
,
name
)
;
pids
.
nnotif
=
graph_matrix_get_edge_g_sorted_list
(
pids
.
notif
,
g
,
name
,
!
requiredby
,
1
)
;
if
(
pids
.
nnotif
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"get sorted "
,
!
requiredby
?
"required by"
:
"dependency"
,
" list of tree: "
,
name
)
;
pids
.
vertex
=
graph_hash_vertex_get_id
(
g
,
name
)
;
if
(
pids
.
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
)
FLAGS_SET
(
pids
.
state
,
FLAGS_UP
)
;
else
FLAGS_SET
(
pids
.
state
,
FLAGS_DOWN
)
;
apidt
[
pos
]
=
pids
;
}
}
static
int
handle_signal
(
pidtree_t
*
apidt
,
unsigned
int
what
,
graph_t
*
graph
,
ssexec_t
*
info
)
{
log_flow
()
;
int
ok
=
0
;
for
(;;)
{
int
s
=
selfpipe_read
()
;
switch
(
s
)
{
case
-
1
:
log_dieusys
(
LOG_EXIT_SYS
,
"selfpipe_read"
)
;
case
0
:
return
ok
;
case
SIGCHLD
:
for
(;;)
{
unsigned
int
pos
=
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
(;
pos
<
napid
;
pos
++
)
if
(
apidt
[
pos
].
pid
==
r
)
break
;
if
(
pos
<
napid
)
{
if
(
!
WIFSIGNALED
(
wstat
)
&&
!
WEXITSTATUS
(
wstat
))
{
announce
(
pos
,
apidt
,
info
->
base
.
s
,
what
,
0
,
0
)
;
}
else
{
ok
=
WIFSIGNALED
(
wstat
)
?
WTERMSIG
(
wstat
)
:
WEXITSTATUS
(
wstat
)
;
announce
(
pos
,
apidt
,
info
->
base
.
s
,
what
,
1
,
ok
)
;
kill_all
(
apidt
)
;
break
;
}
npid
--
;
}
}
break
;
case
SIGTERM
:
case
SIGKILL
:
case
SIGINT
:
log_1_warn
(
"received SIGINT, aborting transaction"
)
;
kill_all
(
apidt
)
;
ok
=
111
;
break
;
default
:
log_die
(
LOG_EXIT_SYS
,
"unexpected data in selfpipe"
)
;
}
}
return
ok
;
}
/** this following function come from:
* https://git.skarnet.org/cgi-bin/cgit.cgi/s6-rc/tree/src/s6-rc/s6-rc.c#n111
* under license ISC where parameters was modified */
static
uint32_t
compute_timeout
(
uint32_t
timeout
,
tain
*
deadline
)
{
uint32_t
t
=
timeout
;
int
globalt
;
tain
globaltto
;
tain_sub
(
&
globaltto
,
deadline
,
&
STAMP
)
;
globalt
=
tain_to_millisecs
(
&
globaltto
)
;
if
(
!
globalt
)
globalt
=
1
;
if
(
globalt
>
0
&&
(
!
t
||
(
unsigned
int
)
globalt
<
t
))
t
=
(
uint32_t
)
globalt
;
return
t
;
}
static
int
ssexec_callback
(
stralloc
*
sa
,
ssexec_t
*
info
,
unsigned
int
what
)
{
size_t
pos
=
0
,
len
=
sastr_len
(
sa
),
e
=
1
;
int
n
=
what
==
2
?
2
:
1
;
int
nargc
=
n
+
len
;
char
const
*
prog
=
PROG
;
char
const
*
newargv
[
nargc
]
;
unsigned
int
m
=
0
;
newargv
[
m
++
]
=
"all"
;
if
(
what
==
2
)
newargv
[
m
++
]
=
"-u"
;
FOREACH_SASTR
(
sa
,
pos
)
newargv
[
m
++
]
=
sa
->
s
+
pos
;
newargv
[
m
]
=
0
;
if
(
!
what
)
{
PROG
=
"start"
;
e
=
ssexec_start
(
nargc
,
newargv
,
info
)
;
PROG
=
prog
;
}
else
{
PROG
=
"stop"
;
e
=
ssexec_stop
(
nargc
,
newargv
,
info
)
;
PROG
=
prog
;
}
return
e
;
}
static
int
doit
(
char
const
*
treename
,
ssexec_t
*
sinfo
,
unsigned
int
what
,
tain
*
deadline
)
{
log_flow
()
;
int
r
,
e
=
0
;
ssexec_t
info
=
SSEXEC_ZERO
;
ssexec_copy
(
&
info
,
sinfo
)
;
{
info
.
treename
.
len
=
0
;
if
(
!
auto_stra
(
&
info
.
treename
,
treename
))
log_die_nomem
(
"stralloc"
)
;
info
.
tree
.
len
=
0
;
if
(
!
auto_stra
(
&
info
.
tree
,
treename
))
log_die_nomem
(
"stralloc"
)
;
r
=
tree_sethome
(
&
info
)
;
if
(
r
<=
0
)
log_warnu_return
(
LOG_EXIT_ZERO
,
"find tree: "
,
info
.
treename
.
s
)
;
if
(
!
tree_get_permissions
(
info
.
tree
.
s
,
info
.
owner
))
log_warn_return
(
LOG_EXIT_ZERO
,
"You're not allowed to use the tree: "
,
info
.
tree
.
s
)
;
}
if
(
!
tree_isinitialized
(
info
.
base
.
s
,
info
.
treename
.
s
)
&&
!
what
)
{
if
(
!
what
)
{
int
nargc
=
3
;
char
const
*
prog
=
PROG
;
char
const
*
newargv
[
nargc
]
;
unsigned
int
m
=
0
;
newargv
[
m
++
]
=
"all (child)"
;
newargv
[
m
++
]
=
info
.
treename
.
s
;
newargv
[
m
++
]
=
0
;
PROG
=
"init"
;
if
(
ssexec_init
(
nargc
,
newargv
,
&
info
))
log_warnu_return
(
LOG_EXIT_ZERO
,
"initiate services of tree: "
,
info
.
treename
.
s
)
;
PROG
=
prog
;
}
else
{
log_warn
(
"uninitialized tree: "
,
info
.
treename
.
s
)
;
goto
end
;
}
}
{
stralloc
sa
=
STRALLOC_ZERO
;
char
const
*
exclude
[
2
]
=
{
SS_MASTER
+
1
,
0
}
;
size_t
treelen
=
info
.
tree
.
len
+
SS_SVDIRS_LEN
+
SS_RESOLVE_LEN
;
char
tree
[
treelen
+
1
]
;
auto_strings
(
tree
,
info
.
tree
.
s
,
SS_SVDIRS
,
SS_RESOLVE
)
;
if
(
!
sastr_dir_get
(
&
sa
,
tree
,
exclude
,
S_IFREG
))
log_dieu
(
LOG_EXIT_SYS
,
"get services list from tree: "
,
info
.
treename
.
s
)
;
if
(
!
sa
.
len
)
{
log_info
(
"Empty tree: "
,
info
.
treename
.
s
,
" -- nothing to do"
)
;
}
else
{
if
(
!
ssexec_callback
(
&
sa
,
&
info
,
what
))
goto
err
;
if
(
what
==
2
)
log_info
(
"Unsupervised successfully tree: "
,
info
.
treename
.
s
)
;
}
stralloc_free
(
&
sa
)
;
}
end:
e
=
1
;
err:
ssexec_free
(
&
info
)
;
return
e
;
}
static
int
check_action
(
pidtree_t
*
apidt
,
unsigned
int
pos
,
unsigned
int
receive
,
unsigned
int
what
)
{
unsigned
int
p
=
char2enum
[
receive
]
;
unsigned
char
action
=
actions
[
what
][
p
]
;
switch
(
action
)
{
case
TREE_ACTION_GOTIT
:
FLAGS_SET
(
apidt
[
pos
].
state
,
(
!
what
?
FLAGS_UP
:
FLAGS_DOWN
))
;
return
1
;
case
TREE_ACTION_FATAL
:
FLAGS_SET
(
apidt
[
pos
].
state
,
FLAGS_FATAL
)
;
return
-
1
;
case
TREE_ACTION_WAIT
:
return
0
;
case
TREE_ACTION_UNKNOWN
:
default:
log_die
(
LOG_EXIT_ZERO
,
"invalid action -- please make a bug report"
)
;
}
}
static
int
async_deps
(
pidtree_t
*
apidt
,
unsigned
int
i
,
unsigned
int
what
,
ssexec_t
*
info
,
graph_t
*
graph
,
tain
*
deadline
)
{
log_flow
()
;
int
r
;
unsigned
int
pos
=
0
,
id
=
0
,
ilog
=
0
,
idx
=
0
;
char
buf
[(
UINT_FMT
*
2
)
*
SS_MAX_SERVICE
+
1
]
;
tain
dead
;
tain_now_set_stopwatch_g
()
;
tain_add_g
(
&
dead
,
deadline
)
;
iopause_fd
x
=
{
.
fd
=
apidt
[
i
].
pipe
[
0
],
.
events
=
IOPAUSE_READ
,
0
}
;
unsigned
int
n
=
apidt
[
i
].
nedge
;
unsigned
int
visit
[
n
]
;
graph_array_init_single
(
visit
,
n
)
;
while
(
pos
<
n
)
{
r
=
iopause_g
(
&
x
,
1
,
&
dead
)
;
if
(
r
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"iopause"
)
;
if
(
!
r
)
{
errno
=
ETIMEDOUT
;
log_dieusys
(
LOG_EXIT_SYS
,
"time out"
,
pares
[
apidt
[
i
].
aresid
].
sa
.
s
+
pares
[
apidt
[
i
].
aresid
].
name
)
;
}
if
(
x
.
revents
&
IOPAUSE_READ
)
{
memset
(
buf
,
0
,
sizeof
(
buf
))
;
r
=
read
(
apidt
[
i
].
pipe
[
0
],
buf
,
sizeof
(
buf
))
;
if
(
r
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"read from pipe"
)
;
buf
[
r
]
=
0
;
idx
=
0
;
while
(
r
!=
-
1
)
{
/** The buf might contain multiple signal coming
* from the dependencies if they finished before
* the start of this read process. Check every
* signal received.*/
r
=
get_len_until
(
buf
+
idx
,
'@'
)
;
if
(
r
<
0
)
/* no more signal */
goto
next
;
char
line
[
r
+
1
]
;
memcpy
(
line
,
buf
+
idx
,
r
)
;
line
[
r
]
=
0
;
idx
+=
r
+
1
;
/**
* the received string have the format:
* index_of_the_ares_array_of_the_tree_dependency:signal_receive
*
* typically:
* - 10:D
* - 30:u
* - ...
*
* Split it and check the signal receive.*/
int
sep
=
get_len_until
(
line
,
':'
)
;
if
(
sep
<
0
)
log_die
(
LOG_EXIT_SYS
,
"received bad signal format -- please make a bug report"
)
;
unsigned
int
c
=
line
[
sep
+
1
]
;
char
pc
[
2
]
=
{
c
,
0
}
;
line
[
sep
]
=
0
;
if
(
!
uint0_scan
(
line
,
&
id
))
log_dieusys
(
LOG_EXIT_SYS
,
"retrieve service number -- please make a bug report"
)
;
ilog
=
id
;
log_trace
(
pares
[
apidt
[
i
].
aresid
].
sa
.
s
+
pares
[
apidt
[
i
].
aresid
].
name
,
" acknowledges: "
,
pc
,
" from: "
,
pares
[
ilog
].
sa
.
s
+
pares
[
ilog
].
name
)
;
if
(
!
visit
[
pos
])
{
id
=
pidtree_get_id
(
apidt
,
id
)
;
if
(
id
<
0
)
log_dieu
(
LOG_EXIT_SYS
,
"get apidtree id -- please make a bug report"
)
;
id
=
check_action
(
apidt
,
id
,
c
,
what
)
;
if
(
id
<
0
)
log_die
(
LOG_EXIT_SYS
,
"tree dependency: "
,
pares
[
ilog
].
sa
.
s
+
pares
[
ilog
].
name
,
" of: "
,
pares
[
apidt
[
i
].
aresid
].
sa
.
s
+
pares
[
apidt
[
i
].
aresid
].
name
,
" crashed"
)
;
if
(
!
id
)
continue
;
visit
[
pos
++
]
++
;
}
}
}
next:
}
return
1
;
}
static
int
async
(
pidtree_t
*
apidt
,
unsigned
int
i
,
unsigned
int
what
,
ssexec_t
*
info
,
graph_t
*
graph
,
tain
*
deadline
)
{
log_flow
()
;
int
e
=
0
;
char
*
name
=
graph
->
data
.
s
+
genalloc_s
(
graph_hash_t
,
&
graph
->
hash
)[
apidt
[
i
].
vertex
].
vertex
;
log_trace
(
"beginning of the process of: "
,
name
)
;
if
(
FLAGS_ISSET
(
apidt
[
i
].
state
,
(
!
what
?
FLAGS_DOWN
:
FLAGS_UP
))
||
/** force to pass through unsupersive process even
* if the tree is marked down */
FLAGS_ISSET
(
apidt
[
i
].
state
,
(
what
?
FLAGS_DOWN
:
FLAGS_UP
))
&&
what
==
2
)
{
if
(
!
FLAGS_ISSET
(
apidt
[
i
].
state
,
FLAGS_BLOCK
))
{
FLAGS_SET
(
apidt
[
i
].
state
,
FLAGS_BLOCK
)
;
if
(
apidt
[
i
].
nedge
)
if
(
!
async_deps
(
apidt
,
i
,
what
,
info
,
graph
,
deadline
))
log_warnu_return
(
LOG_EXIT_ZERO
,
!
what
?
"start"
:
"stop"
,
" dependencies of tree: "
,
name
)
;
e
=
doit
(
name
,
info
,
what
,
deadline
)
;
}
else
{
log_trace
(
"skipping tree: "
,
name
,
" -- already in "
,
what
?
"stopping"
:
"starting"
,
" process"
)
;
notify
(
apidt
,
i
,
what
?
"d"
:
"u"
,
what
)
;
}
}
else
{
/** do not notify here, the handle will make it for us */
log_trace
(
"skipping service: "
,
name
,
" -- already "
,
what
?
"down"
:
"up"
)
;
}
return
e
;
}
static
int
waitit
(
pidtree_t
*
apidt
,
unsigned
int
what
,
graph_t
*
graph
,
tain
*
deadline
,
ssexec_t
*
info
)
{
log_flow
()
;
unsigned
int
e
=
0
,
pos
=
0
;
int
r
;
pid_t
pid
;
pidtree_t
apidtreetable
[
napid
]
;
pidtree_t_ref
apidtree
=
apidtreetable
;
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
(
SIGKILL
)
||
!
selfpipe_trap
(
SIGTERM
)
||
!
sig_altignore
(
SIGPIPE
))
log_dieusys
(
LOG_EXIT_SYS
,
"selfpipe_trap"
)
;
iopause_fd
x
=
{
.
fd
=
spfd
,
.
events
=
IOPAUSE_READ
,
.
revents
=
0
}
;
for
(;
pos
<
napid
;
pos
++
)
{
apidtree
[
pos
]
=
apidt
[
pos
]
;
if
(
pipe
(
apidtree
[
pos
].
pipe
)
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"pipe"
);
}
for
(
pos
=
0
;
pos
<
napid
;
pos
++
)
{
pid
=
fork
()
;
if
(
pid
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"fork"
)
;
if
(
!
pid
)
{
selfpipe_finish
()
;
close
(
apidtree
[
pos
].
pipe
[
1
])
;
e
=
async
(
apidtree
,
pos
,
what
,
info
,
graph
,
deadline
)
;
goto
end
;
}
apidtree
[
pos
].
pid
=
pid
;
close
(
apidtree
[
pos
].
pipe
[
0
])
;
npid
++
;
}
while
(
npid
)
{
r
=
iopause_g
(
&
x
,
1
,
deadline
)
;
if
(
r
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"iopause"
)
;
if
(
!
r
)
{
errno
=
ETIMEDOUT
;
log_diesys
(
LOG_EXIT_SYS
,
"time out"
)
;
}
if
(
x
.
revents
&
IOPAUSE_READ
)
{
e
=
handle_signal
(
apidtree
,
what
,
graph
,
info
)
;
if
(
e
)
break
;
}
}
selfpipe_finish
()
;
end:
for
(
pos
=
0
;
pos
<
napid
;
pos
++
)
{
close
(
apidtree
[
pos
].
pipe
[
1
])
;
close
(
apidtree
[
pos
].
pipe
[
0
])
;
}
return
e
;
}
int
ssexec_all
(
int
argc
,
char
const
*
const
*
argv
,
ssexec_t
*
info
)
{
log_flow
()
;
int
r
,
shut
=
0
,
fd
;
tain
deadline
;
uint8_t
what
=
0
,
requiredby
=
0
,
found
=
0
;
stralloc
sa
=
STRALLOC_ZERO
;
size_t
pos
=
0
;
unsigned
int
areslen
=
0
,
list
[
SS_MAX_SERVICE
],
visit
[
SS_MAX_SERVICE
]
;
resolve_tree_t
ares
[
SS_MAX_SERVICE
]
;
resolve_wrapper_t_ref
wres
=
0
;
graph_t
graph
=
GRAPH_ZERO
;
{
subgetopt
l
=
SUBGETOPT_ZERO
;
for
(;;)
{
int
opt
=
subgetopt_r
(
argc
,
argv
,
OPTS_ALL
,
&
l
)
;
if
(
opt
==
-
1
)
break
;
switch
(
opt
)
{
case
'f'
:
shut
=
1
;
break
;
default
:
log_usage
(
usage_all
)
;
}
}
argc
-=
l
.
ind
;
argv
+=
l
.
ind
;
}
if
(
argc
<
1
)
log_usage
(
usage_all
)
;
info
->
treename
.
len
=
0
;
if
(
argv
[
1
])
{
if
(
!
auto_stra
(
&
info
->
treename
,
argv
[
1
]))
log_die_nomem
(
"stralloc"
)
;
}
if
(
info
->
timeout
)
tain_from_millisecs
(
&
deadline
,
info
->
timeout
)
;
else
deadline
=
tain_infinite_relative
;
what
=
parse_signal
(
*
argv
)
;
reloadmsg
=
what
;
if
(
what
)
requiredby
=
1
;
if
((
svc_scandir_ok
(
info
->
scandir
.
s
))
<=
0
)
log_die
(
LOG_EXIT_SYS
,
"scandir: "
,
info
->
scandir
.
s
,
" is not running"
)
;
graph_build_tree
(
&
graph
,
info
->
base
.
s
,
E_RESOLVE_TREE_MASTER_ENABLED
)
;
if
(
!
graph
.
mlen
)
log_die
(
LOG_EXIT_USER
,
"trees selection is not created -- creates its first"
)
;
graph_array_init_single
(
visit
,
SS_MAX_SERVICE
)
;
if
(
!
graph_matrix_sort_tosa
(
&
sa
,
&
graph
))
log_dieu
(
LOG_EXIT_SYS
,
"get list of trees for graph -- please make a bug report"
)
;
FOREACH_SASTR
(
&
sa
,
pos
)
{
char
*
treename
=
sa
.
s
+
pos
;
/** only on tree */
if
(
info
->
treename
.
len
)
{
if
(
!
strcmp
(
info
->
treename
.
s
,
treename
))
found
=
1
;
else
continue
;
}
if
(
tree_resolve_array_search
(
ares
,
areslen
,
treename
)
<
0
)
{
resolve_tree_t
tres
=
RESOLVE_TREE_ZERO
;
/** need to make a copy of the resolve due of the freed
* of the wres struct at the end of the process */
resolve_tree_t
cp
=
RESOLVE_TREE_ZERO
;
wres
=
resolve_set_struct
(
DATA_TREE
,
&
tres
)
;
if
(
!
resolve_read_g
(
wres
,
info
->
base
.
s
,
treename
))
log_dieu
(
LOG_EXIT_SYS
,
"read resolve file of: "
,
treename
,
" -- please make a bug report"
)
;
tree_resolve_copy
(
&
cp
,
&
tres
)
;
ares
[
areslen
++
]
=
cp
;
resolve_free
(
wres
)
;
}
unsigned
int
l
[
graph
.
mlen
],
c
=
0
,
pos
=
0
,
idx
=
0
;
idx
=
graph_hash_vertex_get_id
(
&
graph
,
treename
)
;
if
(
!
visit
[
idx
])
{
/** avoid double entry */
list
[
napid
++
]
=
idx
;
visit
[
idx
]
=
1
;
}
/** find dependencies of the tree from the graph, do it recursively */
c
=
graph_matrix_get_edge_g_sorted_list
(
l
,
&
graph
,
treename
,
requiredby
,
1
)
;
/** append to the list to deal with */
for
(;
pos
<
c
;
pos
++
)
{
if
(
!
visit
[
l
[
pos
]])
{
list
[
napid
++
]
=
l
[
pos
]
;
visit
[
l
[
pos
]]
=
1
;
}
}
if
(
found
)
break
;
}
pidtree_t
apidt
[
graph
.
mlen
]
;
pares
=
ares
;
pareslen
=
&
areslen
;
pidtree_init_array
(
list
,
napid
,
apidt
,
&
graph
,
ares
,
areslen
,
info
,
requiredby
)
;
if
(
shut
)
{
pid_t
pid
;
int
wstat
=
0
;
pid
=
fork
()
;
if
(
pid
<
0
)
log_dieusys
(
LOG_EXIT_SYS
,
"fork"
)
;
if
(
!
pid
)
{
all_redir_fd
()
;
}
else
{
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
;
}
}
if
(
!
areslen
)
{
log_warn
(
"empty trees -- nothing to do"
)
;
r
=
0
;
goto
end
;
}
r
=
waitit
(
apidt
,
what
,
&
graph
,
&
deadline
,
info
)
;
end:
if
(
shut
)
{
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
)
;
}
graph_free_all
(
&
graph
)
;
stralloc_free
(
&
sa
)
;
tree_resolve_array_free
(
ares
,
areslen
)
;
return
r
;
}
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