mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-29 21:43:55 +08:00
Improved fork reporting
Made autosuggestion work properly for tilde expansion
This commit is contained in:
parent
dc23af6b32
commit
0e3eb38f11
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
4
common.h
4
common.h
|
@ -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
1
env.h
|
@ -184,6 +184,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool g_log_forks;
|
extern bool g_log_forks;
|
||||||
|
extern int g_fork_count;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
10
exec.cpp
10
exec.cpp
|
@ -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 )
|
||||||
|
|
|
@ -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);
|
||||||
|
|
16
parser.h
16
parser.h
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user