2 * ion/mod_statusbar/statusd-launch.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
10 #include <sys/types.h>
16 #include <libtu/minmax.h>
17 #include <libextl/readconfig.h>
18 #include <libmainloop/exec.h>
19 #include <libmainloop/select.h>
20 #include <libmainloop/signal.h>
21 #include <ioncore/saveload.h>
22 #include <ioncore/bindmaps.h>
23 #include <ioncore/global.h>
24 #include <ioncore/ioncore.h>
26 #include "statusbar.h"
29 #define CF_STATUSD_TIMEOUT_SEC 3
35 static bool process_pipe(int fd
, ExtlFn fn
,
36 bool *doneseen
, bool *eagain
)
43 n
=read(fd
, buf
, BL
-1);
46 if(errno
==EAGAIN
|| errno
==EINTR
){
47 *eagain
=(errno
==EAGAIN
);
50 warn_err_obj(TR("reading a pipe"));
55 return extl_call(fn
, "s", "b", &buf
, doneseen
);
62 static bool wait_statusd_init(int outfd
, int errfd
, ExtlFn dh
, ExtlFn eh
)
65 struct timeval tv
, endtime
, now
;
66 int nfds
=MAXOF(outfd
, errfd
);
68 bool dummy
, doneseen
, eagain
=FALSE
;
70 if(mainloop_gettime(&endtime
)!=0){
76 endtime
.tv_sec
+=CF_STATUSD_TIMEOUT_SEC
;
81 /* Calculate remaining time */
82 if(now
.tv_sec
>endtime
.tv_sec
){
84 }else if(now
.tv_sec
==endtime
.tv_sec
){
85 if(now
.tv_usec
>=endtime
.tv_usec
)
88 tv
.tv_usec
=endtime
.tv_usec
-now
.tv_usec
;
90 tv
.tv_usec
=USEC
+endtime
.tv_usec
-now
.tv_usec
;
91 tv
.tv_sec
=-1+endtime
.tv_sec
-now
.tv_sec
;
92 /* Kernel lameness tuner: */
93 tv
.tv_sec
+=tv
.tv_usec
/USEC
;
100 retval
=select(nfds
+1, &rfds
, NULL
, NULL
, &tv
);
102 if(FD_ISSET(errfd
, &rfds
)){
103 if(!process_pipe(errfd
, eh
, &dummy
, &eagain
))
106 if(FD_ISSET(outfd
, &rfds
)){
107 if(!process_pipe(outfd
, dh
, &doneseen
, &eagain
))
110 /* Read rest of errors. */
113 ok
=process_pipe(errfd
, eh
, &dummy
, &eagain
);
114 }while(ok
&& !eagain
);
122 if(mainloop_gettime(&now
)!=0){
131 /* Just complain to stderr, not startup error log, and do not fail.
132 * The system might just be a bit slow. We can continue, but without
133 * initial values for the meters, geometry adjustments may be necessary
134 * when we finally get that information.
136 ioncore_warn_nolog(TR("ion-statusd timed out."));
142 int mod_statusbar__launch_statusd(const char *cmd
,
143 ExtlFn initdatahandler
,
144 ExtlFn initerrhandler
,
149 int outfd
=-1, errfd
=-1;
154 pid
=mainloop_do_spawn(cmd
, NULL
, NULL
,
155 NULL
, &outfd
, &errfd
);
160 if(!wait_statusd_init(outfd
, errfd
, initdatahandler
, initerrhandler
))
163 if(!mainloop_register_input_fd_extlfn(outfd
, datahandler
))
166 if(!mainloop_register_input_fd_extlfn(errfd
, errhandler
))
172 mainloop_unregister_input_fd(outfd
);
179 /* statusd automatically exits when notion dies. However, when notion is
180 * restarted (i.e. notioncore.restart()), the new notion process is simply
181 * execve'ed on top of the old one, therefore the ion-statusd process must
182 * be explicitly terminated on deinit. This function should be called
183 * from Lua on deinit with the ion-statusd process id generated above.
186 int mod_statusbar__terminate_statusd(int pid
)
192 /* Send SIGHUP to the specified statusd process to indicate
193 * that we're done. */
194 kill( (pid_t
)pid
, SIGHUP
);