Improved fork reporting

Made autosuggestion work properly for tilde expansion
This commit is contained in:
ridiculousfish 2012-04-21 20:08:08 -07:00
parent dc23af6b32
commit 0e3eb38f11
6 changed files with 42 additions and 18 deletions

View File

@ -1961,7 +1961,7 @@ void append_path_component(wcstring &path, const wcstring &component)
} }
extern "C" { extern "C" {
__attribute__((noinline)) void debug_thread_error(void) {} __attribute__((noinline)) void debug_thread_error(void) { while (1) sleep(9999999); }
} }
@ -2015,11 +2015,11 @@ void assert_is_background_thread(const char *who)
} }
} }
void assert_is_locked(void *vmutex, const char *who) void assert_is_locked(void *vmutex, const char *who, const char *caller)
{ {
pthread_mutex_t *mutex = static_cast<pthread_mutex_t*>(vmutex); pthread_mutex_t *mutex = static_cast<pthread_mutex_t*>(vmutex);
if (0 == pthread_mutex_trylock(mutex)) { if (0 == pthread_mutex_trylock(mutex)) {
fprintf(stderr, "Warning: %s is not locked when it should be. Break on debug_thread_error to debug.\n", who); fprintf(stderr, "Warning: %s is not locked when it should be in '%s'. Break on debug_thread_error to debug.\n", who, caller);
debug_thread_error(); debug_thread_error();
pthread_mutex_unlock(mutex); pthread_mutex_unlock(mutex);
} }

View File

@ -268,8 +268,8 @@ void assert_is_background_thread(const char *who);
#define ASSERT_IS_BACKGROUND_THREAD() ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(__FUNCTION__) #define ASSERT_IS_BACKGROUND_THREAD() ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(__FUNCTION__)
/* Useful macro for asserting that a lock is locked. This doesn't check whether this thread locked it, which it would be nice if it did, but here it is anyways. */ /* Useful macro for asserting that a lock is locked. This doesn't check whether this thread locked it, which it would be nice if it did, but here it is anyways. */
void assert_is_locked(void *mutex, const char *who); void assert_is_locked(void *mutex, const char *who, const char *caller);
#define ASSERT_IS_LOCKED(x) assert_is_locked((void *)(&x), #x) #define ASSERT_IS_LOCKED(x) assert_is_locked((void *)(&x), #x, __FUNCTION__)
/** /**
Converts the wide character string \c in into it's narrow Converts the wide character string \c in into it's narrow

1
env.h
View File

@ -184,6 +184,7 @@ public:
}; };
extern bool g_log_forks; extern bool g_log_forks;
extern int g_fork_count;
#endif #endif

View File

@ -690,7 +690,7 @@ void exec( parser_t &parser, job_t *j )
{ {
/* Call fork. No need to wait for threads since our use is confined and simple. */ /* Call fork. No need to wait for threads since our use is confined and simple. */
if (g_log_forks) { if (g_log_forks) {
printf("Executing keepalive fork for '%ls'\n", j->command_wcstr()); printf("fork #%d: Executing keepalive fork for '%ls'\n", g_fork_count, j->command_wcstr());
} }
keepalive.pid = execute_fork(false); keepalive.pid = execute_fork(false);
if( keepalive.pid == 0 ) if( keepalive.pid == 0 )
@ -1101,7 +1101,7 @@ void exec( parser_t &parser, job_t *j )
/* We don't have to drain threads here because our child process is simple */ /* We don't have to drain threads here because our child process is simple */
if (g_log_forks) { if (g_log_forks) {
printf("Executing fork for internal buffer for '%ls'\n", p->argv0() ? p->argv0() : L"(null)"); printf("fork #%d: Executing fork for internal buffer for '%ls'\n", g_fork_count, p->argv0() ? p->argv0() : L"(null)");
} }
pid = execute_fork(false); pid = execute_fork(false);
if( pid == 0 ) if( pid == 0 )
@ -1173,7 +1173,7 @@ void exec( parser_t &parser, job_t *j )
if (! skip_fork && ! j->io) { if (! skip_fork && ! j->io) {
/* PCA for some reason, fish forks a lot, even for basic builtins like echo just to write out their buffers. I'm certain a lot of this is unnecessary, but I am not sure exactly when. If j->io is NULL, then it means there's no pipes or anything, so we can certainly just write out our data. Beyond that, we may be able to do the same if io_get returns 0 for STDOUT_FILENO and STDERR_FILENO. */ /* PCA for some reason, fish forks a lot, even for basic builtins like echo just to write out their buffers. I'm certain a lot of this is unnecessary, but I am not sure exactly when. If j->io is NULL, then it means there's no pipes or anything, so we can certainly just write out our data. Beyond that, we may be able to do the same if io_get returns 0 for STDOUT_FILENO and STDERR_FILENO. */
if (g_log_forks) { if (g_log_forks) {
printf("Skipping fork for internal builtin for '%ls' (io is %p, job_io is %p)\n", p->argv0(), io, j->io); printf("fork #-: Skipping fork for internal builtin for '%ls' (io is %p, job_io is %p)\n", p->argv0(), io, j->io);
} }
const wcstring &out = get_stdout_buffer(), &err = get_stderr_buffer(); const wcstring &out = get_stdout_buffer(), &err = get_stderr_buffer();
char *outbuff = wcs2str(out.c_str()), *errbuff = wcs2str(err.c_str()); char *outbuff = wcs2str(out.c_str()), *errbuff = wcs2str(err.c_str());
@ -1269,7 +1269,9 @@ void exec( parser_t &parser, job_t *j )
const wchar_t *reader_current_filename(); const wchar_t *reader_current_filename();
if (g_log_forks) { if (g_log_forks) {
printf("forking for '%s' in '%ls'\n", actual_cmd, reader_current_filename()); const wchar_t *file = reader_current_filename();
const wchar_t *func = parser_t::principal_parser().is_function();
printf("fork #%d: forking for '%s' in '%ls:%ls'\n", g_fork_count, actual_cmd, file ? file : L"", func ? func : L"?");
} }
pid = execute_fork(false); pid = execute_fork(false);
if( pid == 0 ) if( pid == 0 )

View File

@ -561,7 +561,9 @@ bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_di
{ {
wcstring dir = tok_last( &tok ); wcstring dir = tok_last( &tok );
wcstring suggested_path; wcstring suggested_path;
if (is_potential_path(dir, &suggested_path, true /* require directory */)) { if (is_potential_path(dir, &suggested_path, true /* require directory */)) {
/* suggested_path needs to actually have dir as a prefix (perhaps with different case). Handle stuff like ./ */ /* suggested_path needs to actually have dir as a prefix (perhaps with different case). Handle stuff like ./ */
bool wants_dot_slash = string_prefixes_string(L"./", dir); bool wants_dot_slash = string_prefixes_string(L"./", dir);
bool has_dot_slash = string_prefixes_string(L"./", suggested_path); bool has_dot_slash = string_prefixes_string(L"./", suggested_path);
@ -572,6 +574,25 @@ bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_di
suggested_path.erase(0, 2); suggested_path.erase(0, 2);
} }
bool wants_tilde = string_prefixes_string(L"~", dir);
bool has_tilde = string_prefixes_string(L"~", suggested_path);
if (wants_tilde && ! has_tilde) {
// The input string has a tilde, the output string does not
// Extract the tilde part, expand it, see if the expansion prefixes the suggestion
// If so, replace it with the tilde part
size_t slash_idx = dir.find(L'/');
const wcstring tilde_part(dir, 0, slash_idx); //note that slash_idx is npos this will return everything
// Expand the tilde
wcstring expanded_tilde = tilde_part;
expand_tilde(expanded_tilde);
// Replace it
if (string_prefixes_string(expanded_tilde, suggested_path)) {
suggested_path.replace(0, expanded_tilde.size(), tilde_part);
}
}
suggestion = str; suggestion = str;
suggestion.erase(tok_get_pos(&tok)); suggestion.erase(tok_get_pos(&tok));
suggestion.append(suggested_path); suggestion.append(suggested_path);

View File

@ -307,14 +307,6 @@ class parser_t {
parser_t(const parser_t&); parser_t(const parser_t&);
parser_t& operator=(const parser_t&); parser_t& operator=(const parser_t&);
/**
Returns the name of the currently evaluated function if we are
currently evaluating a function, null otherwise. This is tested by
moving down the block-scope-stack, checking every block if it is of
type FUNCTION_CALL.
*/
const wchar_t *is_function() const;
void parse_job_argument_list( process_t *p, job_t *j, tokenizer *tok, std::vector<completion_t>& ); void parse_job_argument_list( process_t *p, job_t *j, tokenizer *tok, std::vector<completion_t>& );
int parse_job( process_t *p, job_t *j, tokenizer *tok ); int parse_job( process_t *p, job_t *j, tokenizer *tok );
void skipped_exec( job_t * j ); void skipped_exec( job_t * j );
@ -326,6 +318,14 @@ class parser_t {
public: public:
std::vector<profile_item_t> profile_items; std::vector<profile_item_t> profile_items;
/**
Returns the name of the currently evaluated function if we are
currently evaluating a function, null otherwise. This is tested by
moving down the block-scope-stack, checking every block if it is of
type FUNCTION_CALL.
*/
const wchar_t *is_function() const;
/** Get the "principal" parser, whatever that is */ /** Get the "principal" parser, whatever that is */
static parser_t &principal_parser(); static parser_t &principal_parser();