Skip to content

Commit

Permalink
Login: redfesign user session handling to omit using modal alert pane…
Browse files Browse the repository at this point in the history
…l - it doesn't work correctly if running inside -preformSelectorOnMainThread method call.
  • Loading branch information
trunkmaster committed Sep 18, 2024
1 parent b7529cd commit ad97c44
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 89 deletions.
2 changes: 1 addition & 1 deletion Applications/Login/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ extern LoginExitCode panelExitCode;
@interface Controller (UserSession)

- (void)openSessionForUser:(NSString *)userName;
- (void)userSessionWillClose:(UserSession *)session;
- (void)closeUserSession:(UserSession *)session;

@end

Expand Down
168 changes: 83 additions & 85 deletions Applications/Login/Controller.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@
static NSString *PAMSessionOpeningException = @"PAMSessionOpeningException";

LoginExitCode panelExitCode;
static NSString *consoleLogPath = nil;

//=============================================================================
// Manage user sessions
//=============================================================================
@implementation Controller (UserSession)

// This methods runs in session thread or with performSelectorOnMainThread.
// In the latter case modal mode works without correct buttons update.
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
Expand All @@ -68,90 +69,73 @@ - (void)observeValueForKeyPath:(NSString *)keyPath
return;
}

NSRunAlertPanel(@"Login", @"Something", @"OK", @"Cancel", nil);
// if (session.exitStatus == ShutdownExitCode) { // Shutdown from Workspace
// [self performSelectorOnMainThread:@selector(shutDown:) withObject:self waitUntilDone:NO];
// } else if (session.exitStatus == RebootExitCode) { // Reboot from Workspace
// [self performSelectorOnMainThread:@selector(restart:) withObject:self waitUntilDone:NO];
// } else if (session.exitStatus != 0) { // Workspace crashed
[self runAlertPanelForSession:session];
// }

// dispatch_sync(dispatch_get_main_queue(), ^{
// if (session.exitStatus != 0 && session.exitStatus != ShutdownExitCode &&
// session.exitStatus != RebootExitCode) {
if ([self runAlertPanelForSession:session] == NSAlertAlternateReturn) { // Quit
[self closeAllXClients];
} else { // Restart
session.isRunning = YES;
}
[alert release];
// });
// // if (session.exitStatus != 0 && session.exitStatus != ShutdownExitCode &&
// // session.exitStatus != RebootExitCode) {
// if ([self runAlertPanelForSession:session] == NSAlertAlternateReturn) { // Quit
// [self closeAllXClients];
// } else { // Restart
// session.isRunning = YES;
// }
// [alert release];

if (session.isRunning == NO) {
[session removeObserver:self forKeyPath:@"isRunning"];
[self userSessionWillClose:session];
}

if (session.exitStatus == ShutdownExitCode) {
[self performSelectorOnMainThread:@selector(shutDown:) withObject:self waitUntilDone:NO];
} else if (session.exitStatus == RebootExitCode) {
[self performSelectorOnMainThread:@selector(restart:) withObject:self waitUntilDone:NO];
}
// if (session.isRunning == NO) {
// [session removeObserver:self forKeyPath:@"isRunning"];
// [self closeUserSession:session];
// }
}

- (void)openSessionForUser:(NSString *)user
{
UserSession *aSession;
UserSession *session;

aSession = [[UserSession alloc] initWithOwner:self
session = [[UserSession alloc] initWithOwner:self
name:user
defaults:(NSDictionary *)prefs];
[aSession readSessionScript];
[aSession addObserver:self
[session readSessionScript];
[session addObserver:self
forKeyPath:@"isRunning"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:aSession];
[userSessions setObject:aSession forKey:user]; // remember user session
[aSession release];

// --- GCD code ---
// dispatch_queue_t session_q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t session_q = dispatch_queue_create("ns.login.session", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(session_q, ^{
@autoreleasepool {
// do {
NSLog(@"Session Log (openSessionForUser:) - %@", aSession.sessionLog);

[aSession launchSessionScript];

// if (aSession.exitStatus != 0 && aSession.exitStatus != ShutdownExitCode &&
// aSession.exitStatus != RebootExitCode) {
// [self performSelectorOnMainThread:@selector(userSessionWillClose:)
// withObject:aSession
// waitUntilDone:YES];
// dispatch_sync(dispatch_get_main_queue(), ^{
// [self userSessionWillClose:aSession];
// if ([self runAlertPanelForSession:aSession] == NSAlertAlternateReturn) {
// [self closeAllXClients];
// aSession.isRunning = NO;
// } else {
// aSession.isRunning = YES;
// }
// [alert release];
// });
// }
// } while (aSession != nil && aSession.isRunning != NO);
NSLog(@"(openSessionForUser:) session was FINISHED! Is running: %@", aSession.isRunning ? @"YES" : @"NO");

// if (aSession.exitStatus == ShutdownExitCode) {
// [self performSelectorOnMainThread:@selector(shutDown:) withObject:self waitUntilDone:NO];
// } else if (aSession.exitStatus == RebootExitCode) {
// [self performSelectorOnMainThread:@selector(restart:) withObject:self waitUntilDone:NO];
// }

// This will release UserSession object
// [self userSessionWillClose:aSession];
}
});
context:session];
[userSessions setObject:session forKey:user]; // remember user session
[session release];

[self runUserSession:session];

NSLog(@"(openSessionForUser:) session was STARTED!");
// ----------------
}

- (NSInteger)runAlertPanelForSession:(UserSession *)session
- (void)runUserSession:(UserSession *)session
{
if (session.run_queue == NULL) {
session.run_queue = dispatch_queue_create("ns.login.session", DISPATCH_QUEUE_CONCURRENT);
}

dispatch_async(session.run_queue, ^{
NSLog(@"Session Log (openSessionForUser:) - %@", session.sessionLog);

[session launchSessionScript];
// [session performSelectorOnMainThread:@selector(setRunning:)
// withObject:[NSNumber numberWithBool:YES]
// waitUntilDone:YES];
// sleep(1);
// [session performSelectorOnMainThread:@selector(setRunning:)
// withObject:[NSNumber numberWithBool:NO]
// waitUntilDone:YES];

NSLog(@"(openSessionForUser:) session was FINISHED! Is running: %@",
session.isRunning ? @"YES" : @"NO");
});
}

- (void)runAlertPanelForSession:(UserSession *)session
{
alert = [[NXTAlert alloc]
initWithTitle:@"Login"
Expand All @@ -165,23 +149,26 @@ - (NSInteger)runAlertPanelForSession:(UserSession *)session

[alert setButtonsTarget:self];
[alert setButtonsAction:@selector(alertButtonPressed:)];
alert.representedObject = session;

consoleLogPath = session.sessionLog;
NSLog(@"Console log for %@ - %@", session.userName, session.sessionLog);

// [alert show];
// return [NSApp runModalForWindow:[alert panel]];
return [alert runModal];
[alert show];
}

- (void)alertButtonPressed:(id)sender
{
UserSession *session = alert.representedObject;

switch ([sender tag]) {
case NSAlertDefaultReturn:
// NSLog(@"Alert Panel: start from scratch.");
// NSLog(@"Alert Panel: Restart session.");
[self runUserSession:session];
break;
case NSAlertAlternateReturn:
// NSLog(@"Alert Panel: Kill Them All!");
// NSLog(@"Alert Panel: Quit session.");
[session removeObserver:self forKeyPath:@"isRunning"];
[self closeUserSession:session];
break;
case NSAlertOtherReturn:
// NSLog(@"Alert Panel: show console.log contents.");
Expand All @@ -190,22 +177,25 @@ - (void)alertButtonPressed:(id)sender
// NSLog(@"Adding accessory view to Alert Panel.");
NSTextView *textView = [consoleLogView documentView];
[textView setFont:[NSFont userFixedPitchFontOfSize:10.0]];
[textView setString:[NSString stringWithContentsOfFile:consoleLogPath]];
[textView setString:[NSString stringWithContentsOfFile:session.sessionLog]];
[alert setAccessoryView:consoleLogView];
[sender setEnabled:NO];
}
return;
default:
NSLog(@"Alert Panel: user has made a strange choice!");
}
[NSApp stopModalWithCode:[sender tag]];
[[sender window] orderOut:self];
// [NSApp stopModalWithCode:[sender tag]];
[[alert panel] orderOut:self];
[alert release];
}

- (void)userSessionWillClose:(UserSession *)session
- (void)closeUserSession:(UserSession *)session
{
NSLog(@"Session WILL close for user \'%@\' [%lu] exitStatus: %lu",
session.userName, [session retainCount], session.exitStatus);
NSInteger exitStatus = session.exitStatus;

NSLog(@"Session WILL close for user \'%@\' [%lu] exitStatus: %lu", session.userName,
[session retainCount], exitStatus);

if ([userSessions objectForKey:session.userName] == nil) {
return;
Expand All @@ -220,10 +210,12 @@ - (void)userSessionWillClose:(UserSession *)session
// TODO: actually this doesn't make sense because no multiple session handling
// implemented yet. Leave it for the future.
if ([[userSessions allKeys] count] == 0) {
if (session.exitStatus != ShutdownExitCode && session.exitStatus != RebootExitCode) {
if (exitStatus != ShutdownExitCode && exitStatus != RebootExitCode) {
[self setWindowVisible:YES];
}
}
} else {
NSLog(@"closeUserSession: session still running - will not be closed.");
}
}

Expand Down Expand Up @@ -548,6 +540,13 @@ - (void)awakeFromNib
NSRect rect;
NSString *user;

if (userSessions) {
// Already called - may be called by alert panel log view
return;
}

userSessions = [[NSMutableDictionary alloc] init];

NSLog(@"awakeFromNib");

// Adjust window size to background image size
Expand All @@ -574,7 +573,6 @@ - (void)awakeFromNib

[password setEchosBullets:NO];

userSessions = [[NSMutableDictionary alloc] init];

panelExitCode = 0;
NSLog(@"awakeFromNib: end");
Expand Down
15 changes: 12 additions & 3 deletions Applications/Login/UserSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,26 @@

@class Controller;

typedef enum {
QuittRequest = 128,
ShutdownRequest = 129,
RebootRequest = 130,
RestartRequest = 131
} SessionRequestCode;

@interface UserSession : NSObject
{
Controller *appController;
NSDictionary *appDefaults;
NSMutableArray *sessionScript;
}

@property (assign) BOOL isRunning;
@property (assign) dispatch_queue_t run_queue;
@property (assign) BOOL isRunning;
@property (readonly) NSInteger exitStatus;
@property (readonly) NSString *userName;
@property (readonly) NSString *sessionLog;
@property (assign) SessionRequestCode request;
@property (readonly) NSString *userName;
@property (readonly) NSString *sessionLog;

// ---

Expand Down

0 comments on commit ad97c44

Please sign in to comment.