void* work_on_array(void* temp_lock) { Lock lock_tmp = (Lock)temp_lock; int i; bool is_change = false; get_write_lock(lock_tmp); counter++; release_exclusive_lock(lock_tmp); for (i = 0; i < ARR_SIZE; ++i) { get_may_write_lock(lock_tmp); if (array[i] == (pthread_self() % ARR_SIZE)) { upgrade_may_write_lock(lock_tmp); array[i] = pthread_self(); printf("Thread number: %d was here :)\n", array[i]); is_change = true; break; } release_shared_lock(lock_tmp); } if (is_change) { release_exclusive_lock(lock_tmp); } return NULL; }
void* work_on_array4(void* temp_lock) { Lock lock_tmp = (Lock)temp_lock; int i; for (i = ARR_SIZE - 1; i >= 0; i -= 2) { get_write_lock(lock_tmp); array[i] += 3; release_exclusive_lock(lock_tmp); } return NULL; }
int open_logfile_obj(obj_t *logfile) { /* (Re)opens the specified 'logfile' obj. * Since this logfile can be re-opened after the daemon has chdir()'d, * it must be specified with an absolute pathname. * Returns 0 if the logfile is successfully opened; o/w, returns -1. */ char dirname[PATH_MAX]; int flags; char *now; char *msg; assert(logfile != NULL); assert(is_logfile_obj(logfile)); assert(logfile->name != NULL); assert(logfile->name[0] == '/'); assert(logfile->aux.logfile.console != NULL); assert(logfile->aux.logfile.console->name != NULL); if (logfile->fd >= 0) { if (close(logfile->fd) < 0) /* log err and continue */ log_msg(LOG_WARNING, "Unable to close logfile \"%s\": %s", logfile->name, strerror(errno)); logfile->fd = -1; } /* Perform conversion specifier expansion. */ if (logfile->aux.logfile.fmtName) { char buf[MAX_LINE]; if (format_obj_string(buf, sizeof(buf), logfile->aux.logfile.console, logfile->aux.logfile.fmtName) < 0) { log_msg(LOG_WARNING, "Unable to open logfile for [%s]: filename exceeded buffer", logfile->aux.logfile.console->name); logfile->fd = -1; return(-1); } free(logfile->name); logfile->name = create_string(buf); } /* Create intermediate directories. */ if (get_dir_name(logfile->name, dirname, sizeof(dirname))) { (void) create_dirs(dirname); } /* Only truncate on the initial open if ZeroLogs was enabled. */ flags = O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK; if (logfile->aux.logfile.gotTruncate) { logfile->aux.logfile.gotTruncate = 0; flags |= O_TRUNC; } if ((logfile->fd = open(logfile->name, flags, S_IRUSR | S_IWUSR)) < 0) { log_msg(LOG_WARNING, "Unable to open logfile \"%s\": %s", logfile->name, strerror(errno)); return(-1); } if (logfile->aux.logfile.opts.enableLock && (get_write_lock(logfile->fd) < 0)) { log_msg(LOG_WARNING, "Unable to lock \"%s\"", logfile->name); close(logfile->fd); /* ignore err on close() */ logfile->fd = -1; return(-1); } logfile->gotEOF = 0; set_fd_nonblocking(logfile->fd); /* redundant, just playing it safe */ set_fd_closed_on_exec(logfile->fd); now = create_long_time_string(0); msg = create_format_string("%sConsole [%s] log opened at %s%s", CONMAN_MSG_PREFIX, logfile->aux.logfile.console->name, now, CONMAN_MSG_SUFFIX); write_obj_data(logfile, msg, strlen(msg), 0); free(now); free(msg); /* * Since the above console log message is not marked "informational", * the test in write_obj_data() to re-init the line state will not * be triggered. Thusly, we re-initialize the line state here. */ logfile->aux.logfile.lineState = CONMAN_LOG_LINE_INIT; DPRINTF((9, "Opened [%s] logfile: fd=%d file=%s.\n", logfile->aux.logfile.console->name, logfile->fd, logfile->name)); return(0); }
static void open_daemon_logfile(server_conf_t *conf) { /* (Re)opens the daemon logfile. * Since this logfile can be re-opened after the daemon has chdir()'d, * it must be specified with an absolute pathname. */ static int once = 1; const char *mode = "a"; mode_t mask; char dirname[PATH_MAX]; FILE *fp = NULL; int fd; assert(conf->logFileName != NULL); assert(conf->logFileName[0] == '/'); assert(!conf->enableForeground); /* Only truncate logfile at startup if needed. */ if (once) { if (conf->enableZeroLogs) { mode = "w"; } once = 0; } /* Perform conversion specifier expansion. */ if (conf->logFmtName) { char buf[MAX_LINE]; if (format_obj_string(buf, sizeof(buf), NULL, conf->logFmtName) < 0) { log_msg(LOG_WARNING, "Unable to open daemon logfile: filename too long"); goto err; } free(conf->logFileName); conf->logFileName = create_string(buf); } /* Protect logfile against unauthorized writes by removing * group+other write-access from current mask. */ mask = umask(0); umask(mask | 022); /* * Create intermediate directories. */ if (get_dir_name(conf->logFileName, dirname, sizeof(dirname))) { (void) create_dirs(dirname); } /* Open the logfile. */ fp = fopen(conf->logFileName, mode); umask(mask); if (!fp) { log_msg(LOG_WARNING, "Unable to open daemon logfile \"%s\": %s", conf->logFileName, strerror(errno)); goto err; } if ((fd = fileno(fp)) < 0) { log_msg(LOG_WARNING, "Unable to obtain descriptor for daemon logfile \"%s\": %s", conf->logFileName, strerror(errno)); goto err; } if (get_write_lock(fd) < 0) { log_msg(LOG_WARNING, "Unable to lock daemon logfile \"%s\"", conf->logFileName); goto err; } set_fd_closed_on_exec(fd); /* * Transition to new log file. */ log_set_file(fp, conf->logFileLevel, 1); if (conf->logFilePtr) { if (fclose(conf->logFilePtr) == EOF) { log_msg(LOG_WARNING, "Unable to close daemon logfile \"%s\"", conf->logFileName); } } conf->logFilePtr = fp; DPRINTF((9, "Opened logfile \"%s\": fd=%d.\n", conf->logFileName, fd)); return; err: if (fp) { (void) fclose(fp); } /* Abandon old log file and go logless. */ log_set_file(NULL, 0, 0); if (conf->logFilePtr) { if (fclose(conf->logFilePtr) == EOF) { log_msg(LOG_WARNING, "Unable to close daemon logfile \"%s\"", conf->logFileName); } } conf->logFilePtr = NULL; return; }
int open_serial_obj(obj_t *serial) { /* (Re)opens the specified 'serial' obj. * Returns 0 if the serial console is successfully opened; o/w, returns -1. * * FIXME: Check to see if "downed" serial consoles are ever resurrected. */ int fd; int flags; struct termios tty; assert(serial != NULL); assert(is_serial_obj(serial)); if (serial->fd >= 0) { write_notify_msg(serial, LOG_INFO, "Console [%s] disconnected from \"%s\"", serial->name, serial->aux.serial.dev); set_tty_mode(&serial->aux.serial.tty, serial->fd); if (close(serial->fd) < 0) /* log err and continue */ log_msg(LOG_WARNING, "Unable to close [%s] device \"%s\": %s", serial->name, serial->aux.serial.dev, strerror(errno)); serial->fd = -1; } flags = O_RDWR | O_NONBLOCK | O_NOCTTY; if ((fd = open(serial->aux.serial.dev, flags)) < 0) { log_msg(LOG_WARNING, "Unable to open [%s] device \"%s\": %s", serial->name, serial->aux.serial.dev, strerror(errno)); goto err; } if (get_write_lock(fd) < 0) { log_msg(LOG_WARNING, "Unable to lock [%s] device \"%s\"", serial->name, serial->aux.serial.dev); goto err; } if (!isatty(fd)) { log_msg(LOG_WARNING, "[%s] device \"%s\" not a terminal", serial->name, serial->aux.serial.dev); goto err; } /* According to the UNIX Programming FAQ v1.37 * <http://www.faqs.org/faqs/unix-faq/programmer/faq/> * (Section 3.6: How to Handle a Serial Port or Modem), * systems seem to differ as to whether a nonblocking * open on a tty will affect subsequent read()s. * Play it safe and be explicit! */ set_fd_nonblocking(fd); set_fd_closed_on_exec(fd); /* * Note that while the initial state of the console dev's termios * are saved, the 'opts' settings are not. This is because the * settings do not change until the obj is destroyed, at which time * the termios is reverted back to its initial state. * * FIXME: Re-evaluate this thinking since a SIGHUP should attempt * to resurrect "downed" serial objs. */ get_tty_mode(&serial->aux.serial.tty, fd); get_tty_raw(&tty, fd); set_serial_opts(&tty, serial, &serial->aux.serial.opts); set_tty_mode(&tty, fd); serial->fd = fd; serial->gotEOF = 0; /* * Success! */ write_notify_msg(serial, LOG_INFO, "Console [%s] connected to \"%s\"", serial->name, serial->aux.serial.dev); DPRINTF((9, "Opened [%s] serial: fd=%d dev=%s bps=%d.\n", serial->name, serial->fd, serial->aux.serial.dev, bps_to_int(serial->aux.serial.opts.bps))); return(0); err: if (fd >= 0) { close(fd); /* ignore errors */ } return(-1); }