Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
b2194941
Commit
b2194941
authored
Oct 18, 2015
by
Matthias Braun
Browse files
Remove lpp_server the client parts are already removed anyway
parent
28c24f7a
Changes
2
Hide whitespace changes
Inline
Side-by-side
support/lpp_server/lpp_server.c
deleted
100644 → 0
View file @
28c24f7a
/*
* This file is part of libFirm.
* Copyright (C) 2012 Universitaet Karlsruhe
*/
#ifdef _WIN32
#error Sorry, lpp_server is for UNIX only.
#endif
#include
<sys/types.h>
#include
<sys/socket.h>
#include
<sys/time.h>
#include
<sys/resource.h>
#include
<sys/wait.h>
#include
<sys/ipc.h>
#include
<sys/sem.h>
#include
<netinet/in.h>
#include
<netdb.h>
#include
<unistd.h>
#include
<pthread.h>
#include
<time.h>
#include
<time.h>
#include
<errno.h>
#include
<signal.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<string.h>
#include
"debug.h"
#include
"list.h"
#include
"util.h"
#include
"lpp_t.h"
#include
"lpp_comm.h"
#include
"lpp_solvers.h"
#define MAX_JOBS 128
/* stack size of the solver thread. */
static
size_t
solver_stack_size
=
PTHREAD_STACK_MIN
;
/* master listening socket. */
static
int
msock
;
/* master semaphore */
static
int
sem
;
/* title of the current process */
static
char
*
title
;
static
int
title_length
;
static
int
n_children
=
0
;
extern
char
**
environ
;
typedef
struct
_job_t
{
struct
list_head
list
;
int
id
;
pthread_t
solver
;
pthread_t
session
;
lpp_comm_t
*
comm
;
lpp_t
*
lpp
;
lpp_solver_func_t
*
solver_func
;
time_t
received
;
int
csock
;
}
job_t
;
#define set_solver_stack_size(size) solver_stack_size = MAX(PTHREAD_STACK_MIN, (size))
#define setproctitle(name, args...) snprintf(title,title_length,(name),##args)
static
void
initproctitle
(
int
argc
,
char
**
argv
)
{
int
i
;
char
**
envp
=
environ
;
/*
* Move the environment so we can reuse the memory.
* (Code borrowed from sendmail.)
* WARNING: ugly assumptions on memory layout here;
* if this ever causes problems, #undef DO_PS_FIDDLING
*/
for
(
i
=
0
;
envp
[
i
]
!=
NULL
;
i
++
)
continue
;
environ
=
(
char
**
)
malloc
(
sizeof
(
char
*
)
*
(
i
+
1
));
if
(
environ
==
NULL
)
return
;
for
(
i
=
0
;
envp
[
i
]
!=
NULL
;
i
++
)
if
((
environ
[
i
]
=
strdup
(
envp
[
i
]))
==
NULL
)
return
;
environ
[
i
]
=
NULL
;
title
=
argv
[
0
];
if
(
i
>
0
)
title_length
=
envp
[
i
-
1
]
+
strlen
(
envp
[
i
-
1
])
-
argv
[
0
];
else
title_length
=
argv
[
argc
-
1
]
+
strlen
(
argv
[
argc
-
1
])
-
argv
[
0
];
argv
[
1
]
=
NULL
;
memset
(
title
,
0
,
title_length
);
--
title_length
;
}
static
void
job_init
(
job_t
*
job
,
lpp_comm_t
*
comm
,
lpp_t
*
lpp
,
lpp_solver_func_t
*
solver_func
)
{
/* TODO MAXJOBS */
memset
(
job
,
0
,
sizeof
(
job
[
0
]));
job
->
lpp
=
lpp
;
job
->
solver_func
=
solver_func
;
job
->
comm
=
comm
;
job
->
csock
=
lpp_comm_fileno
(
comm
);
job
->
received
=
time
(
NULL
);
job
->
session
=
pthread_self
();
job
->
id
=
getpid
();
}
static
firm_dbg_module_t
*
dbg
=
NULL
;
/**
* Set up a socket.
*/
static
int
passive_tcp
(
uint16_t
port
,
int
queue_len
)
{
int
s
;
int
one
=
1
;
struct
protoent
*
ppe
;
struct
sockaddr_in
sin
;
memset
(
&
sin
,
0
,
sizeof
(
sin
));
sin
.
sin_family
=
AF_INET
;
sin
.
sin_addr
.
s_addr
=
INADDR_ANY
;
sin
.
sin_port
=
htons
(
port
);
ppe
=
getprotobyname
(
"tcp"
);
s
=
socket
(
PF_INET
,
SOCK_STREAM
,
ppe
->
p_proto
);
setsockopt
(
s
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
one
,
sizeof
(
one
));
if
(
bind
(
s
,
(
struct
sockaddr
*
)
&
sin
,
sizeof
(
sin
))
<
0
)
{
perror
(
"bind server socket"
);
exit
(
1
);
}
if
(
listen
(
s
,
queue_len
)
<
0
)
{
perror
(
"listen server socket"
);
exit
(
1
);
}
return
s
;
}
static
void
*
solver_thread
(
void
*
data
)
{
job_t
*
job
=
data
;
DBG
((
dbg
,
LEVEL_1
,
"starting solver thread pid %d tid %d
\n
"
,
getpid
(),
pthread_self
()));
setproctitle
(
"lpp_server [problem solving: %s]"
,
job
->
lpp
->
name
);
/* I may be cancelled at every time. */
pthread_setcanceltype
(
PTHREAD_CANCEL_ASYNCHRONOUS
,
NULL
);
/* solve */
job
->
solver_func
(
job
->
lpp
);
/* notify the session thread that we are finished. */
fclose
(
job
->
lpp
->
log
);
return
NULL
;
}
static
int
solve
(
lpp_comm_t
*
comm
,
job_t
*
job
)
{
char
buf
[
1024
];
struct
timeval
tv
;
fd_set
rfds
;
int
fds
[
2
];
FILE
*
rd
,
*
log
;
int
res
=
0
;
int
retval
,
fd_rd
,
fd_comm
;
pthread_attr_t
solver_thr_attr
;
struct
sembuf
semops
;
/* try to acquire a lock for the solver resource. */
semops
.
sem_num
=
0
;
semops
.
sem_op
=
-
1
;
semops
.
sem_flg
=
SEM_UNDO
;
retval
=
semop
(
sem
,
&
semops
,
1
);
if
(
retval
<
0
)
{
perror
(
"free semaphore"
);
}
DBG
((
dbg
,
LEVEL_1
,
"job %d: solving problem %s
\n
"
,
job
->
id
,
job
->
lpp
->
name
));
/* set the log file of the lpp to the pipe. */
pipe
(
fds
);
DBG
((
dbg
,
LEVEL_4
,
"pipe read %d write %d
\n
"
,
fds
[
0
],
fds
[
1
]));
fd_comm
=
lpp_comm_fileno
(
comm
);
fd_rd
=
fds
[
0
];
rd
=
fdopen
(
fd_rd
,
"r"
);
log
=
fdopen
(
fds
[
1
],
"w"
);
lpp_set_log
(
job
->
lpp
,
log
);
/* also set the stack size of the solver thread to a considerable amount */
pthread_attr_init
(
&
solver_thr_attr
);
pthread_attr_setstacksize
(
&
solver_thr_attr
,
solver_stack_size
);
pthread_create
(
&
job
->
solver
,
&
solver_thr_attr
,
solver_thread
,
job
);
while
(
1
)
{
/* set select timeout to 10 seconds */
tv
.
tv_sec
=
10
;
tv
.
tv_usec
=
0
;
/* set the file descriptors. */
FD_ZERO
(
&
rfds
);
FD_SET
(
fd_rd
,
&
rfds
);
FD_SET
(
fd_comm
,
&
rfds
);
DBG
((
dbg
,
LEVEL_4
,
"select %d %d
\n
"
,
fd_rd
,
fd_comm
));
retval
=
select
(
MAX
(
fd_rd
,
fd_comm
)
+
1
,
&
rfds
,
NULL
,
NULL
,
&
tv
);
DBG
((
dbg
,
LEVEL_4
,
"retval %d
\n
"
,
retval
));
/* an event on one of the descriptors arrived. */
if
(
retval
>
0
)
{
/* A log message arrived. */
if
(
FD_ISSET
(
fd_rd
,
&
rfds
))
{
/* if there is nothing more to read, the child died; we go home now. */
if
(
feof
(
rd
))
break
;
if
(
fgets
(
buf
,
sizeof
(
buf
),
rd
))
{
DBG
((
dbg
,
LEVEL_4
,
"receiving log message %s
\n
"
,
buf
));
/* send the message over the net. */
lpp_writel
(
comm
,
LPP_CMD_INFO
);
lpp_writes
(
comm
,
buf
);
lpp_flush
(
comm
);
}
}
/* A network message arrived. */
if
(
FD_ISSET
(
fd_comm
,
&
rfds
))
{
int
cmd
;
retval
=
read
(
fd_comm
,
&
cmd
,
sizeof
(
cmd
));
if
(
retval
==
0
)
{
DBG
((
dbg
,
LEVEL_2
,
"cancelling solver thread tid %d
\n
"
,
job
->
solver
));
//pthread_cancel(job->solver);
exit
(
1
);
//res = 1;
//break;
}
switch
(
cmd
)
{
/* eat senseless data. */
default:
while
(
read
(
fd_comm
,
&
cmd
,
sizeof
(
cmd
))
>
0
)
{
}
}
res
=
1
;
}
}
}
pthread_join
(
job
->
solver
,
NULL
);
semops
.
sem_num
=
0
;
semops
.
sem_op
=
1
;
semops
.
sem_flg
=
SEM_UNDO
;
retval
=
semop
(
sem
,
&
semops
,
1
);
if
(
retval
<
0
)
{
perror
(
"free semaphore"
);
}
fclose
(
rd
);
return
res
;
}
static
void
*
session
(
int
fd
)
{
lpp_solver_func_t
*
solver
=
lpp_find_solver
(
"dummy"
);
lpp_comm_t
*
comm
=
lpp_comm_new
(
fd
,
LPP_BUFSIZE
);
DBG
((
dbg
,
LEVEL_1
,
"starting session thread pid %d tid %d
\n
"
,
getpid
(),
pthread_self
()));
setproctitle
(
"lpp_server [child]"
);
/* install the signal handler which gets triggered when the child dies. */
DBG
((
dbg
,
LEVEL_1
,
"new thread
\n
"
));
for
(;;)
{
char
buf
[
64
];
int
cmd
=
lpp_readl
(
comm
);
DBG
((
dbg
,
LEVEL_2
,
"command: %s(%d)
\n
"
,
lpp_get_cmd_name
(
cmd
),
cmd
));
setproctitle
(
"lpp_server [command %s(%d)]"
,
lpp_get_cmd_name
(
cmd
),
cmd
);
switch
(
cmd
)
{
/* we could not read from the socket, so the connection died. bail out. */
case
-
1
:
case
LPP_CMD_BAD
:
goto
end
;
case
LPP_CMD_PROBLEM
:
{
job_t
job
;
lpp_t
*
lpp
;
lpp
=
lpp_deserialize
(
comm
);
lpp_deserialize_values
(
comm
,
lpp
,
lpp_value_start
);
DBG
((
dbg
,
LEVEL_3
,
"problem %s received
\n
"
,
lpp
->
name
));
job_init
(
&
job
,
comm
,
lpp
,
solver
);
DBG
((
dbg
,
LEVEL_3
,
"starting job for problem %s
\n
"
,
lpp
->
name
));
setproctitle
(
"lpp_server [problem waiting: %s]"
,
lpp
->
name
);
solve
(
comm
,
&
job
);
lpp_writel
(
comm
,
LPP_CMD_SOLUTION
);
lpp_serialize_stats
(
comm
,
lpp
);
lpp_serialize_values
(
comm
,
lpp
,
lpp_value_solution
);
lpp_flush
(
comm
);
DBG
((
dbg
,
LEVEL_1
,
"job %d: finished with problem %s
\n
"
,
job
.
id
,
lpp
->
name
));
setproctitle
(
"lpp_server [problem finished: %s]"
,
lpp
->
name
);
free_lpp
(
lpp
);
}
break
;
case
LPP_CMD_SOLVER
:
lpp_readbuf
(
comm
,
buf
,
sizeof
(
buf
));
solver
=
lpp_find_solver
(
buf
);
DBG
((
dbg
,
LEVEL_2
,
"setting solver to: %s
\n
"
,
buf
));
//lpp_send_res(comm, solver != NULL, "could not find solver: %s", buf);
break
;
case
LPP_CMD_SOLVERS
:
{
int
i
;
for
(
i
=
0
;
lpp_solvers
[
i
].
solver
!=
NULL
;
i
++
)
{
}
lpp_writel
(
comm
,
i
);
for
(
i
=
0
;
lpp_solvers
[
i
].
solver
!=
NULL
;
i
++
)
lpp_writes
(
comm
,
lpp_solvers
[
i
].
name
);
lpp_flush
(
comm
);
break
;
}
case
LPP_CMD_SET_DEBUG
:
{
int
mask
=
lpp_readl
(
comm
);
firm_dbg_set_mask
(
dbg
,
mask
);
}
break
;
case
LPP_CMD_BYE
:
goto
end
;
default:
fprintf
(
stderr
,
"illegal command %d. exiting
\n
"
,
cmd
);
goto
end
;
}
}
end:
/* signal the queue, bail out and we are free now. */
lpp_comm_free
(
comm
);
close
(
fd
);
exit
(
0
);
}
static
void
child_handler
(
int
sig
)
{
pid_t
pid
;
int
status
;
(
void
)
sig
;
pid
=
waitpid
(
-
1
,
&
status
,
WNOHANG
);
do
{
if
(
WIFEXITED
(
status
))
{
DBG
((
dbg
,
LEVEL_1
,
"child %d died normally with return value %d
\n
"
,
pid
,
WEXITSTATUS
(
status
)));
--
n_children
;
if
(
n_children
!=
0
)
setproctitle
(
"lpp_server [main (%d %s)]"
,
n_children
,
(
n_children
>
1
)
?
"children"
:
"child"
);
else
setproctitle
(
"lpp_server [main]"
);
}
else
if
(
WIFSIGNALED
(
status
))
{
DBG
((
dbg
,
LEVEL_1
,
"child %d died by signal %d
\n
"
,
pid
,
WTERMSIG
(
status
)));
--
n_children
;
if
(
n_children
!=
0
)
setproctitle
(
"lpp_server [main (%d %s)]"
,
n_children
,
(
n_children
>
1
)
?
"children"
:
"child"
);
else
setproctitle
(
"lpp_server [main]"
);
}
else
DBG
((
dbg
,
LEVEL_1
,
"child %d did something unexpected
\n
"
,
pid
));
pid
=
waitpid
(
-
1
,
&
status
,
WNOHANG
);
}
while
(
pid
>
0
);
}
static
void
main_loop
(
void
)
{
int
csock
;
DBG
((
dbg
,
LEVEL_1
,
"master pid %d
\n
"
,
getpid
()));
msock
=
passive_tcp
(
LPP_PORT
,
10
);
for
(;;)
{
struct
sockaddr_in
fsin
;
socklen_t
len
=
sizeof
(
fsin
);
pid_t
child
;
csock
=
accept
(
msock
,
(
struct
sockaddr
*
)
&
fsin
,
&
len
);
if
(
csock
<
0
)
{
if
(
errno
==
EINTR
)
continue
;
else
fprintf
(
stderr
,
"could not accept: %s
\n
"
,
strerror
(
errno
));
}
child
=
fork
();
switch
(
child
)
{
case
0
:
/* we're in the new child, start the session handler */
close
(
msock
);
session
(
csock
);
break
;
case
-
1
:
/* error, die! */
perror
(
"fork"
);
exit
(
1
);
default:
/* if we're in the parent just continue */
++
n_children
;
setproctitle
(
"lpp_server [main (%d %s)]"
,
n_children
,
(
n_children
>
1
)
?
"children"
:
"child"
);
close
(
csock
);
break
;
}
}
}
static
void
toggle_dbg
(
int
num
)
{
static
int
mask
=
0
;
(
void
)
num
;
mask
=
~
mask
;
firm_dbg_set_mask
(
dbg
,
mask
);
}
#define SEMKEYPATH "/tmp/lppkey"
#define SEMKEYID 42
static
void
print_syntax
(
void
)
{
fprintf
(
stderr
,
"lpp_server [-g <dbg level>] [-s <thread stack size>]
\n
"
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
key_t
semkey
;
int
ret
;
int
c
;
struct
sigaction
sigact1
,
sigact2
;
dbg
=
firm_dbg_register
(
"lpp.server"
);
firm_dbg_set_mask
(
dbg
,
1
);
set_solver_stack_size
(
128
*
1024
*
1024
);
/* parse options. */
while
((
c
=
getopt
(
argc
,
argv
,
"s:g:"
))
!=
-
1
)
{
switch
(
c
)
{
case
's'
:
set_solver_stack_size
(
atoi
(
optarg
));
break
;
case
'g'
:
firm_dbg_set_mask
(
dbg
,
atoi
(
optarg
));
break
;
default:
print_syntax
();
exit
(
1
);
}
}
initproctitle
(
argc
,
argv
);
setproctitle
(
"lpp_server [main]"
);
memset
(
&
sigact1
,
0
,
sizeof
(
sigact1
));
sigact1
.
sa_handler
=
toggle_dbg
;
sigaction
(
SIGUSR1
,
&
sigact1
,
NULL
);
memset
(
&
sigact2
,
0
,
sizeof
(
sigact2
));
sigact2
.
sa_handler
=
child_handler
;
sigact2
.
sa_flags
=
SA_NOCLDSTOP
;
sigaction
(
SIGCHLD
,
&
sigact2
,
NULL
);
/* set up semaphore */
semkey
=
ftok
(
SEMKEYPATH
,
SEMKEYID
);
if
(
semkey
==
(
key_t
)
-
1
)
{
perror
(
"ftok() for sem failed"
);
return
1
;
}
sem
=
semget
(
semkey
,
1
,
0666
|
IPC_CREAT
);
// | IPC_EXCL );
if
(
sem
==
-
1
)
{
perror
(
"semget() failed"
);
return
-
1
;
}
ret
=
semctl
(
sem
,
0
,
SETVAL
,
1
);
if
(
ret
<
0
)
{
perror
(
"semctl() failed"
);
return
-
1
;
}
main_loop
();
ret
=
semctl
(
sem
,
0
,
IPC_RMID
);
if
(
ret
<
0
)
{
printf
(
"semctl() remove id failed
\n
"
);
return
-
1
;
}
return
0
;
}
support/lpp_server/lpp_server.h
deleted
100644 → 0
View file @
28c24f7a
/*
* This file is part of libFirm.
* Copyright (C) 2012 Universitaet Karlsruhe
*/
#ifndef LPP_SERVER_H
#define LPP_SERVER_H
#include
<stdio.h>
#include
<stdarg.h>
#include
<stdint.h>
#include
<unistd.h>
#include
<errno.h>
#include
<netinet/in.h>
enum
{
#define LPP_CMD(x) x,
#include
"lpp_cmd.def"
#undef LPP_CMD
LPP_CMD_LAST
};
#define BASIC_ERR_CHECK(expr,cond,fmt,last) \
if((expr) cond) { \
fprintf(stderr, "%s(%d): %s %s: ", __FILE__, __LINE__, #expr, #cond); \
print_err fmt; \
fprintf(stderr, "\n"); \
last; \
}
#define BASIC_ERRNO_CHECK(expr,cond,last) \
if((expr) cond) { \
fprintf(stderr, "%s(%d): %s %s: %s\n", \
__FILE__, __LINE__, #expr, #cond, strerror(errno)); \
last; \
}
#define ERR_CHECK_RETURN(expr, cond, fmt, retval) \
BASIC_ERR_CHECK(expr, cond, fmt, return retval)
#define ERRNO_CHECK_RETURN(expr, cond, retval) \
BASIC_ERRNO_CHECK(expr, cond, return retval)
#define ERR_CHECK_RETURN_VOID(expr, cond, fmt) \
BASIC_ERR_CHECK(expr, cond, fmt, return)
#define ERRNO_CHECK_RETURN_VOID(expr, cond) \
BASIC_ERRNO_CHECK(expr, cond, return)
#define ERR_CHECK(expr, cond, fmt) \
BASIC_ERR_CHECK(expr, cond, fmt, (void) 0)
#define ERRNO_CHECK(expr, cond) \
BASIC_ERRNO_CHECK(expr, cond, (void) 0)
static
void
print_err
(
const
char
*
fmt
,
...)
{
va_list
args
;
va_start
(
args
,
fmt
);
vfprintf
(
stderr
,
fmt
,
args
);
va_end
(
args
);
}
static
void
writel
(
int
fd
,
uint32_t
x
)
{
x
=
htonl
(
x
);
ERRNO_CHECK
(
write
(
fd
,
&
x
,
sizeof
(
x
)),
==
-
1
);
}
static
void
writed
(
int
fd
,
double
dbl
)
{
ERRNO_CHECK
(
write
(
fd
,
&
dbl
,
sizeof
(
dbl
)),
==
-
1
);
}
static
void
writes
(
int
fd
,
const
char
*
str
)
{
size_t
n
=
strlen
(
str
);
writel
(
fd
,
n
);
ERRNO_CHECK
(
write
(
fd
,
str
,
n
),
==
-
1
);
}
static
uint32_t
readl
(
int
fd
)
{
uint32_t
res
;
ERRNO_CHECK
(
read
(
fd
,
&
res
,
sizeof
(
res
)),
==
-
1
);
return
ntohl
(
res
);
}
static
double
readd
(
int
fd
)
{
double
res
;
ERRNO_CHECK
(
read
(
fd
,
&
res
,
sizeof
(
res
)),
==
-
1
);
return
res
;
}
static
char
*
reads
(
int
fd
)
{