1 #define _GNU_SOURCE /* struct ucred */
7 #include <sys/resource.h>
8 #include <sys/socket.h>
20 daemon_chat(char *cmd
)
22 int s
= socket(AF_UNIX
, SOCK_STREAM
, 0);
23 struct sockaddr_un sun
= { .sun_family
= AF_UNIX
, .sun_path
= SOCKFILE
};
24 if (connect(s
, (struct sockaddr
*) &sun
, sizeof(sun
.sun_family
) + strlen(sun
.sun_path
) + 1) < 0) {
26 fputs("Plese contact " ADMINCONTACT
" about this error.\n", stderr
);
32 struct iovec iov_cmd
= {
34 .iov_len
= strlen(cmd
),
41 /* Include credentials in the message. */
47 char cbuf
[CMSG_SPACE(sizeof(cred
))];
48 msg
.msg_control
= cbuf
;
49 msg
.msg_controllen
= sizeof(cbuf
);
50 struct cmsghdr
*cmsg
= CMSG_FIRSTHDR(&msg
);
51 cmsg
->cmsg_level
= SOL_SOCKET
;
52 cmsg
->cmsg_type
= SCM_CREDENTIALS
;
53 cmsg
->cmsg_len
= CMSG_LEN(sizeof(cred
));
54 memcpy(CMSG_DATA(cmsg
), &cred
, sizeof(cred
));
56 ssize_t sent
= sendmsg(s
, &msg
, 0);
61 if ((size_t) sent
< msg
.msg_iov
->iov_len
) {
62 fprintf(stderr
, "incomplete send %zd < %zu, FIXME\n", sent
, msg
.msg_iov
->iov_len
);
69 struct iovec iov_reply
= {
71 .iov_len
= sizeof(reply
),
73 msg
.msg_iov
= &iov_reply
;
77 int replylen
= recvmsg(s
, &msg
, 0);
84 if (replylen
>= 1024) {
85 fprintf(stderr
, "too long reply from the server\n");
97 fputs("compctl - Computations under control\n\n"
98 #include "help-in-quotes"
99 "Contact " ADMINCONTACT
" with bug reports and comments.\n", f
);
103 run(int argc
, char *argv
[])
106 char *line
= daemon_chat("blessme");
107 if (line
[0] != '1') {
108 fprintf(stderr
, "%s\n", *line
? line
: "unexpected hangup");
115 if (setpriority(PRIO_PROCESS
, 0, COMPNICE
) < 0)
116 perror("Warning: setpriority()");
118 char *argvx
[argc
+ 1];
119 for (int i
= 0; i
< argc
; i
++)
122 execvp(argvx
[0], argvx
);
128 screen(int argc
, char *argv
[])
130 char *argvx
[argc
+ 2];
133 for (int i
= 0; i
< argc
; i
++)
134 argvx
[i
+ 2] = argv
[i
];
135 return run(argc
+ 2, argvx
);
142 fputs("Killing computations not possible when computations are not limited..\n", stderr
);
146 char cmd
[256]; snprintf(cmd
, sizeof(cmd
), "kill %d", pid
);
147 char *line
= daemon_chat(cmd
);
148 if (line
[0] != '1') {
149 fprintf(stderr
, "%s\n", *line
? line
: "unexpected hangup");
159 fputs("Killing computations not possible when computations are not limited..\n", stderr
);
163 char *line
= daemon_chat("killall");
164 if (line
[0] != '1') {
165 fprintf(stderr
, "%s\n", *line
? line
: "unexpected hangup");
173 limit_mem(size_t limit
)
176 fputs("Computations are not limited.\n", stderr
);
181 snprintf(cmd
, sizeof(cmd
), "limitmem %zu", limit
* 1048576);
182 char *line
= daemon_chat(cmd
);
183 if (line
[0] != '1') {
184 /* TODO: More error message postprocessing. */
185 fprintf(stderr
, "%s\n", *line
? line
: "unexpected hangup");
186 if (line
[0] == '0') {
187 fprintf(stderr
, "Most likely, the computations are already using too much memory.\n"
188 "Consider killing some of them first.\n");
203 size_t usage
= cgroup_get_mem_usage(chier
, cgroup
);
204 size_t limit
= cgroup_get_mem_limit(chier
, cgroup
);
205 printf("Memory usage:\t%zuM / %zuM\n", usage
/ 1048576, limit
/ 1048576);
212 fputs("List not available when computations are not limited.\n", stderr
);
217 int tasks_n
= cgroup_task_list(chier
, cgroup
, &tasks
);
220 for (int i
= 0; i
< tasks_n
; i
++) {
221 /* TODO: Print process details. */
222 printf("%d\n", tasks
[i
]);
227 main(int argc
, char *argv
[])
231 if (argc
== optind
) {
236 unlimited
= access("/etc/compctl-unlimited", F_OK
) >= 0;
237 if (!unlimited
&& !cgroup_available(chier
, cgroup
)) {
238 fputs("CGroup-based computation control is not available on this host.\n", stderr
);
239 fputs("Most likely, this computer is not meant for computations,\n", stderr
);
240 fputs("please consider switching to a different host.\n", stderr
);
241 fputs("Plese contact " ADMINCONTACT
" if you believe this is an error.\n", stderr
);
245 while (argc
> optind
) {
246 char *cmd
= argv
[optind
++];
247 if (!strcmp(cmd
, "--run")) {
248 if (argc
<= optind
) {
249 fputs("missing arguments for --run\n", stderr
);
252 return run(argc
- optind
, &argv
[optind
]);
254 } else if (!strcmp(cmd
, "--screen")) {
255 if (argc
<= optind
) {
256 fputs("missing arguments for --screen\n", stderr
);
259 return screen(argc
- optind
, &argv
[optind
]);
261 } else if (!strcmp(cmd
, "--usage")) {
264 } else if (!strcmp(cmd
, "--list")) {
267 } else if (!strcmp(cmd
, "--kill")) {
268 if (argc
<= optind
) {
269 fputs("missing argument for --kill\n", stderr
);
272 kill_task(atoi(argv
[optind
++]));
274 } else if (!strcmp(cmd
, "--killall")) {
277 } else if (!strcmp(cmd
, "--limitmem")) {
278 if (argc
<= optind
) {
279 fputs("missing argument for --limitmem\n", stderr
);
282 limit_mem(atol(argv
[optind
++]));
284 } else if (!strcmp(cmd
, "--help")) {