When running in daemon mode, delay parent exit until device is created
Doing this is somewhat elaborate because cuse_lowlevel_main() when daemonizing, the parent (the calling thread) calls _exit(0) instead of returning.
This commit is contained in:
@@ -39,6 +39,8 @@ static struct ttynvt_param {
|
|||||||
/* Derived */
|
/* Derived */
|
||||||
char host[64];
|
char host[64];
|
||||||
unsigned int port;
|
unsigned int port;
|
||||||
|
/* Picked up */
|
||||||
|
int foreground;
|
||||||
} ttynvt_param;
|
} ttynvt_param;
|
||||||
|
|
||||||
typedef struct ttynvt {
|
typedef struct ttynvt {
|
||||||
@@ -80,6 +82,22 @@ static void _log(int prio, const char *fmt, ...)
|
|||||||
if (ttynvt_param.debug) _log(LOG_DEBUG, __VA_ARGS__)
|
if (ttynvt_param.debug) _log(LOG_DEBUG, __VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
static int _check_dev(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char dev_nbuf[128];
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
snprintf(dev_nbuf, sizeof(dev_nbuf), "/dev/%s", ttynvt_param.dev_name);
|
||||||
|
|
||||||
|
rc = stat(dev_nbuf, &st);
|
||||||
|
|
||||||
|
DBG("Checking for %s: %d\n", dev_nbuf, rc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ttynvt_release(fuse_req_t req, struct fuse_file_info *info)
|
static void ttynvt_release(fuse_req_t req, struct fuse_file_info *info)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
||||||
@@ -828,6 +846,8 @@ process_arg(void *data, const char *arg, int key, struct fuse_args *outargs)
|
|||||||
print_help();
|
print_help();
|
||||||
return fuse_opt_add_arg(outargs, "-ho");
|
return fuse_opt_add_arg(outargs, "-ho");
|
||||||
default:
|
default:
|
||||||
|
if (strcmp(arg, "-d") == 0 || strcmp(arg, "-f") == 0)
|
||||||
|
ttynvt_param.foreground = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -839,6 +859,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
char dev_name[128];
|
char dev_name[128];
|
||||||
const char *dev_info_argv[] = { dev_name };
|
const char *dev_info_argv[] = { dev_name };
|
||||||
|
pid_t cpid;
|
||||||
|
|
||||||
openlog("ttynvt", LOG_PID, LOG_DAEMON);
|
openlog("ttynvt", LOG_PID, LOG_DAEMON);
|
||||||
|
|
||||||
@@ -881,5 +902,41 @@ int main(int argc, char *argv[])
|
|||||||
.flags = CUSE_UNRESTRICTED_IOCTL,
|
.flags = CUSE_UNRESTRICTED_IOCTL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (ttynvt_param.foreground)
|
||||||
|
{
|
||||||
return cuse_lowlevel_main(args.argc, args.argv, &ci, &ttynvt_op, NULL);
|
return cuse_lowlevel_main(args.argc, args.argv, &ci, &ttynvt_op, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpid = fork();
|
||||||
|
switch (cpid)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
_log(LOG_ERR, "fork(): %m");
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case 0: /* Child */
|
||||||
|
DBG("Child proceeding...\n");
|
||||||
|
rc = cuse_lowlevel_main(args.argc, args.argv, &ci, &ttynvt_op, NULL);
|
||||||
|
if (rc != 0)
|
||||||
|
_log(LOG_ERR, "ttynvt failed rc=%d", rc);
|
||||||
|
else
|
||||||
|
DBG("Child exited\n");
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
default: /* Parent */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Parent proceeding (child=%d)...\n", cpid);
|
||||||
|
|
||||||
|
for (rc = 0; rc < 10; rc++)
|
||||||
|
{
|
||||||
|
if (_check_dev() == 0)
|
||||||
|
break;
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Parent exiting\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user