|
|
| version 1.6, 2025/04/10 01:24:38 | version 1.12, 2025/05/14 15:28:55 |
|---|---|
| Line 24 | Line 24 |
| * along with FreeM. If not, see <https://www.gnu.org/licenses/>. | * along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
| * | * |
| * $Log$ | * $Log$ |
| * Revision 1.12 2025/05/14 15:28:55 snw | |
| * Get basic job table and lock table functionality working with new shared memory architecture | |
| * | |
| * Revision 1.11 2025/05/14 12:22:04 snw | |
| * Further work on shared memory | |
| * | |
| * Revision 1.10 2025/05/12 18:18:00 snw | |
| * Further work on shared memory | |
| * | |
| * Revision 1.9 2025/05/01 21:02:31 snw | |
| * Documentation updates | |
| * | |
| * Revision 1.8 2025/04/30 20:03:09 snw | |
| * Work on entryref parser | |
| * | |
| * Revision 1.7 2025/04/17 00:34:04 snw | |
| * More logging improvements | |
| * | |
| * Revision 1.6 2025/04/10 01:24:38 snw | * Revision 1.6 2025/04/10 01:24:38 snw |
| * Remove C++ style comments | * Remove C++ style comments |
| * | * |
| Line 41 | Line 59 |
| #include <string.h> | #include <string.h> |
| #include <time.h> | #include <time.h> |
| #include <unistd.h> | #include <unistd.h> |
| #include <errno.h> | |
| #include "mpsdef.h" | #include "mpsdef.h" |
| #include "shmmgr.h" | #include "shmmgr.h" |
| #include "jobtab.h" | #include "jobtab.h" |
| #include "log.h" | |
| #if !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(__OS2__) | #if !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(__OS2__) |
| union semun { | union semun { |
| Line 69 void jobtab_init(void) | Line 89 void jobtab_init(void) |
| semid_jobtab = semget (jt_sk, 1, 0666 | IPC_CREAT); | semid_jobtab = semget (jt_sk, 1, 0666 | IPC_CREAT); |
| if (semid_jobtab == -1) { | if (semid_jobtab == -1) { |
| fprintf (stderr, "jobtab_init: failed to create job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "jobtab_init: failed to create job table semaphore (error code %d [%s])", errno, strerror (errno)); |
| exit (1); | |
| } | } |
| else { | else { |
| fprintf (stderr, "jobtab_init: job table semaphore created with semid %d\r\n", semid_jobtab); | logprintf (FM_LOG_INFO, "jobtab_init: job table semaphore created with semid %d", semid_jobtab); |
| } | } |
| arg.val = 1; | arg.val = 1; |
| if (semctl (semid_jobtab, 0, SETVAL, arg) == -1) { | if (semctl (semid_jobtab, 0, SETVAL, arg) == -1) { |
| fprintf (stderr, "jobtab_init: failed to initialize job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "jobtab_init: failed to initialize job table semaphore (error code %d [%s])", errno, strerror (errno)); |
| exit (1); | |
| } | } |
| else { | else { |
| fprintf (stderr, "jobtab_init: job table semaphore initialized\r\n"); | logprintf (FM_LOG_INFO, "jobtab_init: job table semaphore initialized"); |
| } | } |
| } | } |
| Line 90 void jobtab_init(void) | Line 108 void jobtab_init(void) |
| semid_jobtab = semget (jt_sk, 1, 0); | semid_jobtab = semget (jt_sk, 1, 0); |
| if (semid_jobtab == -1) { | if (semid_jobtab == -1) { |
| fprintf (stderr, "jobtab_init: could not attach to job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "jobtab_init: could not attach to job table semaphore (error code %d [%s])", errno, strerror (errno)); |
| exit (1); | } |
| else { | |
| logprintf (FM_LOG_INFO, "jobtab_init: attached to job table semaphore (semid %d)", semid_jobtab); | |
| } | } |
| } | } |
| Line 104 short jobtab_get_sem(void) | Line 124 short jobtab_get_sem(void) |
| int tries; | int tries; |
| struct sembuf s = {0, -1, IPC_NOWAIT}; | struct sembuf s = {0, -1, IPC_NOWAIT}; |
| logprintf (FM_LOG_DEBUG, "jobtab_get_sem: attempting to acquire job table semaphore"); | |
| if (have_jobtab_sem) { | if (have_jobtab_sem) { |
| logprintf (FM_LOG_DEBUG, "jobtab_get_sem: acquired semaphore by virtue of already owning it"); | |
| return TRUE; | return TRUE; |
| } | } |
| for (tries = 0; tries < 5; tries++) { | for (tries = 0; tries < 5; tries++) { |
| if (semop (semid_jobtab, &s, 1) != -1) { | if (semop (semid_jobtab, &s, 1) != -1) { |
| logprintf (FM_LOG_DEBUG, "jobtab_get_sem: acquired semaphore by virtue of calling semop on it"); | |
| have_jobtab_sem = TRUE; | have_jobtab_sem = TRUE; |
| return TRUE; | return TRUE; |
| } | } |
| /* fprintf (stderr, "jobtab_get_sem: sleeping for retry [tries = %d]\r\n", tries); */ | logprintf (FM_LOG_INFO, "jobtab_get_sem: sleeping for retry [tries = %d; errno = %d; error = %s]", tries, errno, strerror (errno)); |
| sleep (1); | sleep (1); |
| } | } |
| fprintf (stderr, "jobtab_get_sem: fail\r\n"); | logprintf (FM_LOG_ERROR, "jobtab_get_sem: failed to acquire job table semaphore"); |
| have_jobtab_sem = FALSE; | have_jobtab_sem = FALSE; |
| return FALSE; | return FALSE; |
| } | } |
| Line 130 void jobtab_release_sem(void) | Line 153 void jobtab_release_sem(void) |
| { | { |
| struct sembuf s = {0, 1, 0}; | struct sembuf s = {0, 1, 0}; |
| semop (semid_jobtab, &s, 1); | logprintf (FM_LOG_DEBUG, "jobtab_release_sem: trying to release job table semaphore"); |
| if (semop (semid_jobtab, &s, 1) != -1) { | |
| have_jobtab_sem = FALSE; | logprintf (FM_LOG_DEBUG, "jobtab_release_sem: released job table semaphore by means of semop"); |
| have_jobtab_sem = FALSE; | |
| } | |
| else { | |
| logprintf (FM_LOG_FATAL, "jobtab_release_sem: failed to release job table semaphore (error code %d [%s])", errno, strerror (errno)); | |
| } | |
| } | } |
| Line 142 job_slot_t *job_init(short is_fmadm) | Line 170 job_slot_t *job_init(short is_fmadm) |
| job_slot_t *s; | job_slot_t *s; |
| if (jobtab_get_sem () == FALSE) { | if (jobtab_get_sem () == FALSE) { |
| fprintf (stderr, "job_init: failed to get job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "job_init: failed to get job table semaphore"); |
| exit (1); | |
| } | } |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if (((s->flags & JFLG_DEFUNCT) == JFLG_DEFUNCT) || (s->pid == pid)) { | if (((s->flags & JFLG_DEFUNCT) == JFLG_DEFUNCT) || (s->pid == pid)) { |
| goto skip_alloc; | goto skip_alloc; |
| Line 178 skip_alloc: | Line 205 skip_alloc: |
| } | } |
| } | } |
| s->next = shm_config->hdr->jobtab_head; | s->next = SBM(SOA(shm_config->hdr->jobtab_head)); |
| shm_config->hdr->jobtab_head = s; | shm_config->hdr->jobtab_head = SBM(s); |
| jobtab_release_sem (); | jobtab_release_sem (); |
| Line 190 skip_alloc: | Line 217 skip_alloc: |
| void job_remove(const pid_t pid) | void job_remove(const pid_t pid) |
| { | { |
| job_slot_t *t = shm_config->hdr->jobtab_head; | job_slot_t *t = SOM(shm_config->hdr->jobtab_head); |
| job_slot_t *p = NULL; | job_slot_t *p = NULL; |
| if (jobtab_get_sem() == FALSE) { | if (jobtab_get_sem () == FALSE) { |
| fprintf (stderr, "job_remove: failed to get job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "job_remove: failed to get job table semaphore"); |
| exit (1); | |
| } | } |
| if ((t != (job_slot_t *) NULL) && (t->pid == pid)) { | if ((t != (job_slot_t *) NULL) && (t->pid == pid)) { |
| shm_config->hdr->jobtab_head = t->next; | shm_config->hdr->jobtab_head = SBM(SOA(t->next)); |
| shm_free (t); | shm_free (t); |
| jobtab_release_sem (); | jobtab_release_sem (); |
| Line 211 void job_remove(const pid_t pid) | Line 237 void job_remove(const pid_t pid) |
| while ((t != NULL) && (t->pid != pid)) { | while ((t != NULL) && (t->pid != pid)) { |
| p = t; | p = t; |
| t = t->next; | t = SOA(t->next); |
| } | } |
| if (t == NULL) { | if (t == NULL) { |
| Line 219 void job_remove(const pid_t pid) | Line 245 void job_remove(const pid_t pid) |
| return; | return; |
| } | } |
| p->next = t->next; | p->next = SBA(t->next); |
| shm_free (t); | shm_free (t); |
| jobtab_release_sem (); | jobtab_release_sem (); |
| locktab_unlock_all_by_pid (pid); | |
| } | } |
| void job_request_stop(const pid_t target_pid) | void job_request_stop(const pid_t target_pid) |
| Line 232 void job_request_stop(const pid_t target | Line 259 void job_request_stop(const pid_t target |
| job_slot_t *s; | job_slot_t *s; |
| if (jobtab_get_sem() == FALSE) { | if (jobtab_get_sem() == FALSE) { |
| fprintf (stderr, "job_request_stop: failed to get job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "job_request_stop: failed to get job table semaphore"); |
| exit (1); | |
| } | } |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if (s->pid == target_pid) { | if (s->pid == target_pid) { |
| s->stop_requested = pid; | s->stop_requested = pid; |
| Line 258 void job_set_ecode(const pid_t target_pi | Line 284 void job_set_ecode(const pid_t target_pi |
| job_slot_t *s; | job_slot_t *s; |
| if (jobtab_get_sem() == FALSE) { | if (jobtab_get_sem () == FALSE) { |
| fprintf (stderr, "job_set_ecode: failed to get job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "job_set_ecode: failed to get job table semaphore"); |
| exit (1); | |
| } | } |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if (s->pid == target_pid) { | if (s->pid == target_pid) { |
| strncpy (s->last_ecode, ecode, 20); | strncpy (s->last_ecode, ecode, 20); |
| Line 281 pid_t job_stop_requested (const pid_t ta | Line 306 pid_t job_stop_requested (const pid_t ta |
| { | { |
| job_slot_t *s; | job_slot_t *s; |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if (s->pid == target_pid) { | if (s->pid == target_pid) { |
| return s->stop_requested; | return s->stop_requested; |
| } | } |
| Line 299 void job_request_all_stop(void) | Line 323 void job_request_all_stop(void) |
| job_slot_t *s; | job_slot_t *s; |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if ((s->flags & JFLG_DAEMON) != JFLG_DAEMON) { | if ((s->flags & JFLG_DAEMON) != JFLG_DAEMON) { |
| job_request_stop (s->pid); | job_request_stop (s->pid); |
| Line 315 void job_signal_all(const int sig) | Line 339 void job_signal_all(const int sig) |
| job_slot_t *s; | job_slot_t *s; |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if ((s->flags & JFLG_DAEMON) != JFLG_DAEMON) { | if ((s->flags & JFLG_DAEMON) != JFLG_DAEMON) { |
| kill (s->pid, sig); | kill (s->pid, sig); |
| Line 332 int job_count(void) | Line 356 int job_count(void) |
| job_slot_t *s; | job_slot_t *s; |
| int ct = 0; | int ct = 0; |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if ((s->flags & JFLG_DEFUNCT) != JFLG_DEFUNCT) { | if ((s->flags & JFLG_DEFUNCT) != JFLG_DEFUNCT) { |
| ct++; | ct++; |
| Line 349 job_slot_t *job_set_status(const pid_t t | Line 373 job_slot_t *job_set_status(const pid_t t |
| job_slot_t *s; | job_slot_t *s; |
| if (jobtab_get_sem() == FALSE) { | if (jobtab_get_sem () == FALSE) { |
| fprintf (stderr, "job_set_status: failed to get job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "job_set_status: failed to get job table semaphore"); |
| exit (1); | |
| } | } |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if (s->pid == target_pid) { | if (s->pid == target_pid) { |
| s->status = status; | s->status = status; |
| Line 374 void job_gc_mark(void) | Line 397 void job_gc_mark(void) |
| { | { |
| job_slot_t *s; | job_slot_t *s; |
| int jobstat; | |
| if (jobtab_get_sem () == FALSE) { | if (jobtab_get_sem () == FALSE) { |
| fprintf (stderr, "job_gc_mark: failed to get job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "job_gc_mark: failed to get job table semaphore"); |
| exit (1); | |
| } | } |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| logprintf (FM_LOG_WARNING, "job_gc_mark looking at pid %ld", s->pid); | |
| if (kill (s->pid, 0) != 0) { | if ((jobstat = kill (s->pid, 0)) != 0) { |
| fprintf (stderr, "job_gc_mark: marking pid %ld DEFUNCT\r\n", (long) s->pid); | |
| s->flags = JFLG_DEFUNCT; | switch (jobstat) { |
| case EPERM: | |
| logprintf (FM_LOG_WARNING, "job_gc_mark: environment daemon lacks permissions to pid %ld", (long) s->pid); | |
| break; | |
| case ESRCH: | |
| logprintf (FM_LOG_INFO, "job_gc_mark: marking pid %ld DEFUNCT", (long) s->pid); | |
| s->flags = JFLG_DEFUNCT; | |
| break; | |
| } | |
| } | } |
| if ((s->flags & JFLG_NEW) == JFLG_NEW) { | if ((s->flags & JFLG_NEW) == JFLG_NEW) { |
| if ((s->flags & JFLG_DAEMON) == JFLG_DAEMON) { | if ((s->flags & JFLG_DAEMON) == JFLG_DAEMON) { |
| fprintf (stderr, "job_gc_mark: registering new daemon %ld\r\n", (long) s->pid); | logprintf (FM_LOG_INFO, "job_gc_mark: registering new daemon %ld", (long) s->pid); |
| s->flags = JFLG_ALIVE | JFLG_DAEMON; | s->flags = JFLG_ALIVE | JFLG_DAEMON; |
| } | } |
| else { | else { |
| if ((s->flags & JFLG_FMADM) == JFLG_FMADM) { | if ((s->flags & JFLG_FMADM) == JFLG_FMADM) { |
| fprintf (stderr, "job_gc_mark: registering new fmadm process %ld\r\n", (long) s->pid); | logprintf (FM_LOG_INFO, "job_gc_mark: registering new fmadm process %ld", (long) s->pid); |
| s->flags = JFLG_ALIVE | JFLG_FMADM; | s->flags = JFLG_ALIVE | JFLG_FMADM; |
| } | } |
| else { | else { |
| fprintf (stderr, "job_gc_mark: registering new interpreter process %ld\r\n", (long) s->pid); | logprintf (FM_LOG_INFO, "job_gc_mark: registering new interpreter process %ld", (long) s->pid); |
| s->flags = JFLG_ALIVE; | s->flags = JFLG_ALIVE; |
| } | } |
| } | } |
| Line 418 void job_gc_sweep(void) | Line 453 void job_gc_sweep(void) |
| NULLPTRCHK(k_buf,"job_gc_sweep"); | NULLPTRCHK(k_buf,"job_gc_sweep"); |
| if (jobtab_get_sem () == FALSE) { | if (jobtab_get_sem () == FALSE) { |
| fprintf (stderr, "job_gc_sweep: failed to get job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "job_gc_sweep: failed to get job table semaphore"); |
| exit (1); | |
| } | } |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if ((s->flags & JFLG_DEFUNCT) == JFLG_DEFUNCT) { | if ((s->flags & JFLG_DEFUNCT) == JFLG_DEFUNCT) { |
| fprintf (stderr, "job_gc_sweep: sweeping DEFUNCT pid %ld\r\n", (long) s->pid); | logprintf (FM_LOG_INFO, "job_gc_sweep: sweeping DEFUNCT pid %ld", (long) s->pid); |
| snprintf (k_buf, STRLEN - 1, "^$JOB\202%d\201", s->pid); | snprintf (k_buf, STRLEN - 1, "^$JOB\202%d\201", s->pid); |
| Line 458 ipc_slot_t *job_send_ipc(const pid_t rec | Line 492 ipc_slot_t *job_send_ipc(const pid_t rec |
| ipc_slot_t *s = (ipc_slot_t *) shm_alloc (sizeof (ipc_slot_t)); | ipc_slot_t *s = (ipc_slot_t *) shm_alloc (sizeof (ipc_slot_t)); |
| NULLPTRCHK(s,"job_send_ipc"); | NULLPTRCHK(s,"job_send_ipc"); |
| if (jobtab_get_sem() == FALSE) { | if (jobtab_get_sem () == FALSE) { |
| fprintf (stderr, "job_send_ipc: failed to get job table semaphore\r\n"); | logprintf (FM_LOG_FATAL, "job_send_ipc: failed to get job table semaphore"); |
| exit (1); | |
| } | } |
| for (j = shm_config->hdr->jobtab_head; j != NULL; j = j->next) { | for (j = SOA(shm_config->hdr->jobtab_head); j != NULL; j = SOA(j->next)) { |
| if (j->pid == receiver_pid) { | if (j->pid == receiver_pid) { |
| Line 496 job_slot_t *job_get(const pid_t target_p | Line 529 job_slot_t *job_get(const pid_t target_p |
| job_slot_t *s; | job_slot_t *s; |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| if (s->pid == target_pid) return s; | if (s->pid == target_pid) return s; |
| } | } |
| Line 518 void job_dump(void) | Line 551 void job_dump(void) |
| printf ("%-10s%-15s%-20s%-22s%s\r\n", "PID", "STATUS", "LAST ECODE", "STARTED", "FLAGS"); | printf ("%-10s%-15s%-20s%-22s%s\r\n", "PID", "STATUS", "LAST ECODE", "STARTED", "FLAGS"); |
| printf ("%-10s%-15s%-20s%-22s%s\r\n", "---", "------", "----------", "-------", "-----"); | printf ("%-10s%-15s%-20s%-22s%s\r\n", "---", "------", "----------", "-------", "-----"); |
| for (s = shm_config->hdr->jobtab_head; s != NULL; s = s->next) { | for (s = SOA(shm_config->hdr->jobtab_head); s != NULL; s = SOA(s->next)) { |
| strftime (time_buf, 20, "%Y-%m-%d %H:%M:%S", localtime (&(s->start_time))); | strftime (time_buf, 20, "%Y-%m-%d %H:%M:%S", localtime (&(s->start_time))); |